Merge pull request #41 from KevinMidboe/refactor
General refactoring and small feature release
This commit is contained in:
		
							
								
								
									
										26
									
								
								src/api.js
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								src/api.js
									
									
									
									
									
								
							| @@ -62,6 +62,24 @@ const getShow = (id, credits=false) => { | ||||
|     .catch(error => { console.error(`api error getting show: ${id}`); throw error }) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Fetches tmdb person by id. Can optionally include cast credits in result object. | ||||
|  * @param {number} id | ||||
|  * @param {boolean} [credits=false] Include credits | ||||
|  * @returns {object} Tmdb response | ||||
|  */ | ||||
| const getPerson = (id, credits=false) => { | ||||
|   const url = new URL('v2/person', SEASONED_URL) | ||||
|   url.pathname = path.join(url.pathname, id.toString()) | ||||
|   if (credits) { | ||||
|     url.searchParams.append('credits', true) | ||||
|   } | ||||
|  | ||||
|   return fetch(url.href) | ||||
|     .then(resp => resp.json()) | ||||
|     .catch(error => { console.error(`api error getting person: ${id}`); throw error }) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Fetches tmdb list by name. | ||||
|  * @param {string} name List the fetch | ||||
| @@ -110,10 +128,15 @@ const getUserRequests = (page=1) => { | ||||
|  * @param {number} [page=1] | ||||
|  * @returns {object} Tmdb response | ||||
|  */ | ||||
| const searchTmdb = (query, page=1) => { | ||||
| const searchTmdb = (query, page=1, adult=false, mediaType=null) => { | ||||
|   const url = new URL('v2/search', SEASONED_URL) | ||||
|   if (mediaType != null && ['movie', 'show', 'person'].includes(mediaType)) { | ||||
|     url.pathname += `/${mediaType}` | ||||
|   } | ||||
|  | ||||
|   url.searchParams.append('query', query) | ||||
|   url.searchParams.append('page', page) | ||||
|   url.searchParams.append('adult', adult) | ||||
|  | ||||
|   const headers = { authorization: localStorage.getItem('token') } | ||||
|  | ||||
| @@ -424,6 +447,7 @@ const elasticSearchMoviesAndShows = (query) => { | ||||
| export { | ||||
|   getMovie, | ||||
|   getShow, | ||||
|   getPerson, | ||||
|   getTmdbMovieListByName, | ||||
|   searchTmdb, | ||||
|   getUserRequests, | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
|  | ||||
| <template> | ||||
|   <div> | ||||
|     <list-header :title="listTitle" :info="resultCount" :sticky="true" /> | ||||
|     <list-header :title="listTitle" :info="info" :sticky="true" /> | ||||
|  | ||||
|     <results-list :results="results" v-if="results" /> | ||||
|  | ||||
| @@ -30,7 +30,8 @@ export default { | ||||
|       results: [], | ||||
|       page: 1, | ||||
|       totalPages: 0, | ||||
|       totalResults: 0 | ||||
|       totalResults: 0, | ||||
|       loading: true | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
| @@ -42,18 +43,24 @@ export default { | ||||
|       console.log('routelistname', routeListName) | ||||
|       return routeListName.includes('_') ? routeListName.split('_').join(' ') : routeListName | ||||
|     }, | ||||
|     resultCount() { | ||||
|     info() { | ||||
|       if (this.results.length === 0) | ||||
|         return '' | ||||
|  | ||||
|         return [null, null] | ||||
|       return [this.pageCount, this.resultCount] | ||||
|     }, | ||||
|     resultCount() { | ||||
|       const loadedResults = this.results.length | ||||
|       const totalResults = this.totalResults < 10000 ? this.totalResults : '∞' | ||||
|       return `${loadedResults} of ${totalResults} results` | ||||
|     }, | ||||
|     pageCount() { | ||||
|       return `Page ${this.page} of ${this.totalPages}` | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     loadMore() { | ||||
|       console.log(this.$route) | ||||
|       this.loading = true; | ||||
|       this.page++ | ||||
|  | ||||
|       window.history.replaceState({}, 'search', `/#/${this.$route.fullPath}?page=${this.page}`) | ||||
| @@ -82,6 +89,8 @@ export default { | ||||
|         // TODO handle if list is not found | ||||
|         console.log('404 this is not a tmdb list') | ||||
|       } | ||||
|  | ||||
|       this.loading = false | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|   | ||||
| @@ -123,7 +123,7 @@ import SidebarListElement from './ui/sidebarListElem' | ||||
| import store from '@/store' | ||||
| import LoadingPlaceholder from './ui/LoadingPlaceholder' | ||||
|  | ||||
| import { getMovie, getShow, request, getRequestStatus } from '@/api' | ||||
| import { getMovie, getPerson, getShow, request, getRequestStatus } from '@/api' | ||||
|  | ||||
| export default { | ||||
|   props: ['id', 'type'], | ||||
| @@ -140,7 +140,7 @@ export default { | ||||
|       matched: false, | ||||
|       userLoggedIn: storage.sessionId ? true : false, | ||||
|       requested: false, | ||||
|       admin: localStorage.getItem('admin'), | ||||
|       admin: localStorage.getItem('admin') == "true" ? true : false, | ||||
|       showTorrents: false, | ||||
|       compact: false | ||||
|     } | ||||
| @@ -203,6 +203,12 @@ export default { | ||||
|         .catch(error => { | ||||
|           this.$router.push({ name: '404' }); | ||||
|         }) | ||||
|     } else if (this.type == 'person') { | ||||
|        getPerson(this.id, true) | ||||
|         .then(this.parseResponse) | ||||
|         .catch(error => { | ||||
|           this.$router.push({ name: '404' }); | ||||
|         }) | ||||
|     } else { | ||||
|       getShow(this.id) | ||||
|         .then(this.parseResponse) | ||||
|   | ||||
| @@ -13,7 +13,7 @@ | ||||
|         </div> | ||||
|       </figure> | ||||
|       <div class="movies-item__content"> | ||||
|         <p class="movies-item__title">{{ movie.title }}</p> | ||||
|         <p class="movies-item__title">{{ movie.title || movie.name }}</p> | ||||
|         <p class="movies-item__title">{{ movie.year }}</p> | ||||
|       </div> | ||||
|     </a> | ||||
|   | ||||
| @@ -8,10 +8,26 @@ | ||||
|       <seasoned-button @click="loadMore">load more</seasoned-button> | ||||
|     </div> | ||||
|  | ||||
|     <loader v-if="!results.length" /> | ||||
|     <div class="notFound" v-if="results.length == 0 && loading == false"> | ||||
|       <h1 class="notFound-title">No results for search: <b>{{ query }}</b></h1> | ||||
|     </div> | ||||
|  | ||||
|     <loader v-if="loading" /> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .notFound { | ||||
|   display: flex; | ||||
|   justify-content: center; | ||||
|   align-items: center; | ||||
|  | ||||
|   &-title { | ||||
|     font-weight: 400; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
|  | ||||
| <script> | ||||
| import { searchTmdb } from '@/api' | ||||
| import ListHeader from '@/components/ListHeader' | ||||
| @@ -37,6 +53,8 @@ export default { | ||||
|       query: String, | ||||
|       title: String, | ||||
|       page: Number, | ||||
|       adult: undefined, | ||||
|       mediaType: null, | ||||
|       totalPages: 0, | ||||
|       results: [], | ||||
|       totalResults: [] | ||||
| @@ -50,8 +68,8 @@ export default { | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     search(query=this.query, page=this.page) { | ||||
|       searchTmdb(query, page) | ||||
|     search(query=this.query, page=this.page, adult=this.adult, mediaType=this.mediaType) { | ||||
|       searchTmdb(query, page, adult, mediaType) | ||||
|         .then(this.parseResponse) | ||||
|     }, | ||||
|     parseResponse(data) { | ||||
| @@ -74,14 +92,16 @@ export default { | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     const { query, page } = this.$route.query | ||||
|     const { query, page, adult, media_type } = this.$route.query | ||||
|  | ||||
|     if (!query) { | ||||
|       // abort | ||||
|       console.error('abort, no query') | ||||
|     } | ||||
|     this.query = decodeURIComponent(query) | ||||
|     this.page = page ? page : 1 | ||||
|     this.page = page || 1 | ||||
|     this.adult = adult || this.adult | ||||
|     this.mediaType = media_type || this.mediaType | ||||
|     this.title = `Search results: ${this.query}` | ||||
|  | ||||
|     this.search() | ||||
|   | ||||
| @@ -20,9 +20,11 @@ | ||||
|  | ||||
|     <div v-if="listLoaded"> | ||||
|       <div v-if="torrents.length > 0"> | ||||
|         <ul class="filter"> | ||||
|         <!-- <ul class="filter"> | ||||
|           <li class="filter-item" v-for="(item, index) in release_types" @click="applyFilter(item, index)" :class="{'active': item === selectedRelaseType}">{{ item }}</li> | ||||
|         </ul> | ||||
|         </ul> --> | ||||
|  | ||||
|         <toggle-button :options="release_types" :selected.sync="selectedRelaseType" class="toggle"></toggle-button> | ||||
|  | ||||
|  | ||||
|         <table> | ||||
| @@ -97,9 +99,10 @@ import { searchTorrents, addMagnet } from '@/api' | ||||
|  | ||||
| import SeasonedButton from '@/components/ui/SeasonedButton' | ||||
| import SeasonedInput from '@/components/ui/SeasonedInput' | ||||
| import ToggleButton from '@/components/ui/ToggleButton' | ||||
|  | ||||
| export default { | ||||
|   components: { SeasonedButton, SeasonedInput }, | ||||
|   components: { SeasonedButton, SeasonedInput, ToggleButton }, | ||||
|   props: { | ||||
|     query: { | ||||
|       type: String, | ||||
| @@ -110,7 +113,7 @@ export default { | ||||
|       require: true | ||||
|     }, | ||||
|     tmdb_type: String, | ||||
|     admin: String, | ||||
|     admin: Boolean, | ||||
|     show: Boolean | ||||
|   }, | ||||
|   data() { | ||||
| @@ -133,6 +136,11 @@ export default { | ||||
|     } | ||||
|     store.dispatch('torrentModule/reset') | ||||
|   }, | ||||
|   watch: { | ||||
|     selectedRelaseType: function(newValue) { | ||||
|       this.applyFilter(newValue) | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     selectedSortableClass(headerName) { | ||||
|       return headerName === this.prevCol ? 'active' : '' | ||||
| @@ -147,27 +155,31 @@ export default { | ||||
|     expand(event, name) { | ||||
|       const existingExpandedElement = document.getElementsByClassName('expanded')[0] | ||||
|  | ||||
|       const clickedElement = event.target.parentNode; | ||||
|       const scopedStyleDataVariable = Object.keys(clickedElement.dataset)[0] | ||||
|  | ||||
|       if (existingExpandedElement) { | ||||
|         console.log('exists') | ||||
|         const expandedSibling = event.target.parentNode.nextSibling.className === 'expanded' | ||||
|  | ||||
|         existingExpandedElement.remove() | ||||
|         const table = document.getElementsByTagName('table')[0] | ||||
|         table.style.display = 'block' | ||||
|  | ||||
|         if (expandedSibling) { | ||||
|           console.log('sibling is here') | ||||
|           return | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       console.log('expand event', event) | ||||
|       const nameRow = document.createElement('tr') | ||||
|       const nameCol = document.createElement('td') | ||||
|       nameRow.className = 'expanded' | ||||
|       nameRow.dataset[scopedStyleDataVariable] = ""; | ||||
|       nameCol.innerText = name | ||||
|       nameCol.dataset[scopedStyleDataVariable] = ""; | ||||
|  | ||||
|       nameRow.appendChild(nameCol) | ||||
|  | ||||
|       event.target.parentNode.insertAdjacentElement('afterend', nameRow) | ||||
|       clickedElement.insertAdjacentElement('afterend', nameRow) | ||||
|     }, | ||||
|     sendTorrent(magnet, name, event){ | ||||
|       this.$notifications.info({ | ||||
| @@ -177,7 +189,6 @@ export default { | ||||
|       }) | ||||
|  | ||||
|       event.target.parentNode.classList.add('active') | ||||
|  | ||||
|       addMagnet(magnet, name, this.tmdb_id) | ||||
|       .catch((resp) => { console.log('error:', resp.data) }) | ||||
|       .then((resp) => { | ||||
| @@ -193,7 +204,6 @@ export default { | ||||
|       if (this.prevCol === col && sameDirection === false) { | ||||
|         this.direction = !this.direction | ||||
|       } | ||||
|       console.log('col and more', col, sameDirection) | ||||
|  | ||||
|       switch (col) { | ||||
|         case 'name': | ||||
| @@ -279,14 +289,13 @@ export default { | ||||
| @import "./src/scss/variables"; | ||||
| .expanded { | ||||
|   display: flex; | ||||
|   margin: 0 1rem; | ||||
|   padding: 0.25rem 1rem; | ||||
|   max-width: 100%; | ||||
|   border-left: 1px solid $text-color; | ||||
|   border-right: 1px solid $text-color; | ||||
|   border-bottom: 1px solid $text-color; | ||||
|  | ||||
|   td { | ||||
|     // border-left: 1px solid $c-dark; | ||||
|     word-break: break-all; | ||||
|     padding: 0.5rem 0.15rem; | ||||
|     width: 100%; | ||||
| @@ -298,8 +307,14 @@ export default { | ||||
| @import "./src/scss/media-queries"; | ||||
| @import "./src/scss/elements"; | ||||
|  | ||||
| .toggle { | ||||
|   max-width: unset !important; | ||||
|   margin: 1rem 0; | ||||
| } | ||||
|  | ||||
| .container { | ||||
|   background-color: $background-color; | ||||
|   padding: 0 1rem; | ||||
| } | ||||
|  | ||||
| .torrentHeader { | ||||
| @@ -348,7 +363,6 @@ table { | ||||
| .table__content, .table__header { | ||||
|   display: flex; | ||||
|   padding: 0; | ||||
|   margin: 0 1rem; | ||||
|   border-left: 1px solid $text-color; | ||||
|   border-right: 1px solid $text-color; | ||||
|   border-bottom: 1px solid $text-color; | ||||
|   | ||||
| @@ -70,7 +70,7 @@ export default { | ||||
| .message { | ||||
|   width: 100%; | ||||
|   max-width: 35rem; | ||||
|   height: 75px; | ||||
|   min-height: 75px; | ||||
|  | ||||
|   display: flex; | ||||
|   margin-top: 1rem; | ||||
|   | ||||
| @@ -11,13 +11,19 @@ export default { | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       darkmode: window.getComputedStyle(document.body).colorScheme.includes('dark') | ||||
|       darkmode: this.supported | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     toggleDarkmode() { | ||||
|       this.darkmode = !this.darkmode; | ||||
|       document.body.className = this.darkmode ? 'dark' : 'light' | ||||
|     }, | ||||
|     supported() { | ||||
|       const computedStyle = window.getComputedStyle(document.body) | ||||
|       if (computedStyle['colorScheme'] != null) | ||||
|         return computedStyle.colorScheme.includes('dark') | ||||
|       return false | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
| @@ -41,7 +47,7 @@ export default { | ||||
|   margin-right: 2px; | ||||
|   bottom: 0; | ||||
|   right: 0; | ||||
|   z-index: 1; | ||||
|   z-index: 10; | ||||
|  | ||||
|   -webkit-user-select: none; | ||||
|   -moz-user-select: none; | ||||
|   | ||||
| @@ -1,16 +1,18 @@ | ||||
| <template> | ||||
|   <div> | ||||
|     <a @click="$emit('click')"><li> | ||||
|     <a @click="$emit('click')"> | ||||
|       <li> | ||||
|         <figure :class="activeClassIfActive"> | ||||
|         <svg><use :xlink:href="iconRefNameIfActive"/></svg> | ||||
|           <svg class="icon"><use :xlink:href="iconRefNameIfActive"/></svg> | ||||
|         </figure> | ||||
|  | ||||
|       <span :class="activeClassIfActive">{{ contentTextToDisplay }}</span> | ||||
|         <span class="text" :class="activeClassIfActive">{{ contentTextToDisplay }}</span> | ||||
|  | ||||
|         <span v-if="supplementaryText" class="supplementary-text"> | ||||
|           {{ supplementaryText }} | ||||
|         </span> | ||||
|     </li></a> | ||||
|       </li> | ||||
|     </a> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| @@ -44,7 +46,7 @@ export default { | ||||
|     iconRefNameIfActive() { | ||||
|       const { iconRefActive, iconRef, active } = this | ||||
|  | ||||
|       if ((iconRefActive && iconRef) & active) { | ||||
|       if ((iconRefActive && iconRef) && active) { | ||||
|         return iconRefActive | ||||
|       } | ||||
|       return iconRef | ||||
| @@ -85,37 +87,51 @@ li { | ||||
|   &:hover { | ||||
|     color: $text-color-70; | ||||
|     cursor: pointer; | ||||
|  | ||||
|     .icon { | ||||
|       fill: $text-color-70; | ||||
|       cursor: pointer; | ||||
|         transform: scale(1.1, 1.1); | ||||
|     } | ||||
|   } | ||||
|   .active { | ||||
|     color: $text-color; | ||||
|  | ||||
|     .icon { | ||||
|       fill: $green; | ||||
|     } | ||||
|   } | ||||
|   .pending { | ||||
|     color: #f8bd2d; | ||||
|   } | ||||
|  | ||||
|   .text { | ||||
|     margin-left: 26px; | ||||
|   } | ||||
|  | ||||
|   .supplementary-text { | ||||
|     flex-grow: 1; | ||||
|     text-align: right; | ||||
|   } | ||||
|  | ||||
|   figure, figure > svg { | ||||
|     width: 18px; | ||||
|     height: 18px; | ||||
|   figure { | ||||
|     position: absolute; | ||||
|  | ||||
|     > svg { | ||||
|       position: relative; | ||||
|       top: 50%; | ||||
|       width: 16px; | ||||
|       height: 16px; | ||||
|       margin: 0 7px 0 0; | ||||
|       fill: $text-color-50; | ||||
|       transition: fill 0.5s ease, transform 0.5s ease; | ||||
|     &.waiting { | ||||
|  | ||||
|       & .waiting { | ||||
|         transform: scale(0.8, 0.8); | ||||
|       } | ||||
|     &.pending { | ||||
|       & .pending { | ||||
|         fill: #f8bd2d; | ||||
|       } | ||||
|     &:hover &-icon { | ||||
|       fill: $text-color-70; | ||||
|       cursor: pointer; | ||||
|     } | ||||
|     &.active > svg { | ||||
|       fill: $green; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -5,6 +5,31 @@ $tablet-p-width: 768px; | ||||
| $tablet-l-width: 1024px; | ||||
| $desktop-width:  1200px; | ||||
| $desktop-l-width: 1600px; | ||||
| $mobile-width: 768px; | ||||
|  | ||||
| @mixin desktop { | ||||
| 	@media (min-width: #{$mobile-width + 1px}) { | ||||
|     @content; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @mixin mobile { | ||||
| 	@media (max-width: #{$mobile-width}) { | ||||
|     @content; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .desktop-only { | ||||
| 	@include mobile { | ||||
| 		display: none; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| .mobile-only { | ||||
| 	@include desktop { | ||||
| 		display: none; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Media | ||||
| @mixin mobile-only{ | ||||
|   | ||||
| @@ -15,8 +15,8 @@ | ||||
|   --background-95: rgba(255, 255, 255, 0.95); | ||||
|   --background-70: rgba(255, 255, 255, 0.7); | ||||
|   --background-40: rgba(255, 255, 255, 0.4); | ||||
|   --background-nav-logo: #081c24; | ||||
|  | ||||
|   --background-nav-logo: #081c24; | ||||
|   --color-green: #01d277; | ||||
|   --color-green-90: rgba(1, 210, 119, .9); | ||||
|   --color-green-70: rgba(1, 210, 119, .73); | ||||
| @@ -44,12 +44,12 @@ | ||||
|     --text-color-50: rgba(255, 255, 255, 0.5); | ||||
|     --text-color-5: rgba(255, 255, 255, 0.05); | ||||
|     --text-color-secondary: orange; | ||||
|     --background-color: #1e1f22; | ||||
|     --background-color-secondary: #111111; | ||||
|     --background-95: rgba(30, 31, 34, 0.95); | ||||
|     --background-70: rgba(30, 31, 34, 0.8); | ||||
|     --background-40: rgba(30, 31, 34, 0.4); | ||||
|     --background-color: rgba(17, 17, 17, 1); | ||||
|     --background-color-secondary: rgba(6, 7, 8, 1); | ||||
|     --background-ui: #202125; | ||||
|     --background-95: rgba(17, 17, 17, 0.95); | ||||
|     --background-70: rgba(17, 17, 17, 0.8); | ||||
|     --background-40: rgba(17, 17, 17, 0.4); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -104,12 +104,12 @@ $color-error-highlight: var(--color-error-highlight) !default; | ||||
|   --text-color-50: rgba(255, 255, 255, 0.5); | ||||
|   --text-color-5: rgba(255, 255, 255, 0.05); | ||||
|   --text-color-secondary: orange; | ||||
|   --background-color: #1e1f22; | ||||
|   --background-color-secondary: #111111; | ||||
|   --background-95: rgba(30, 31, 34, 0.95); | ||||
|   --background-70: rgba(30, 31, 34, 0.7); | ||||
|   --background-color: rgba(17, 17, 17, 1); | ||||
|   --background-color-secondary: rgba(6, 7, 8, 1); | ||||
|   --background-ui: #202125; | ||||
|   --color-teal: #091c24; | ||||
|   --background-95: rgba(17, 17, 17, 0.95); | ||||
|   --background-70: rgba(17, 17, 17, 0.8); | ||||
|   --background-40: rgba(17, 17, 17, 0.4); | ||||
| } | ||||
|  | ||||
| .light { | ||||
| @@ -117,14 +117,11 @@ $color-error-highlight: var(--color-error-highlight) !default; | ||||
|   --text-color-70: rgba(8, 28, 36, 0.7); | ||||
|   --text-color-50: rgba(8, 28, 36, 0.5); | ||||
|   --text-color-5: rgba(8, 28, 36, 0.05); | ||||
|   --text-color-inverted: #fff; | ||||
|   --text-color-secondary: orange; | ||||
|   --background-color: #f8f8f8; | ||||
|   --background-color-secondary: #ffffff; | ||||
|   --background-ui: #edeef0; | ||||
|   --background-95: rgba(255, 255, 255, 0.95); | ||||
|   --background-70: rgba(255, 255, 255, 0.7); | ||||
|   --background-ui: #edeef0; | ||||
|   --background-nav-logo: #081c24; | ||||
|   --color-green: #01d277; | ||||
|   --color-teal: #091c24; | ||||
|   --background-40: rgba(255, 255, 255, 0.4); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user