Merge pull request #41 from KevinMidboe/refactor

General refactoring and small feature release
This commit is contained in:
2019-12-27 22:04:36 +01:00
committed by GitHub
11 changed files with 191 additions and 74 deletions

View File

@@ -62,6 +62,24 @@ const getShow = (id, credits=false) => {
.catch(error => { console.error(`api error getting show: ${id}`); throw error }) .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. * Fetches tmdb list by name.
* @param {string} name List the fetch * @param {string} name List the fetch
@@ -110,10 +128,15 @@ const getUserRequests = (page=1) => {
* @param {number} [page=1] * @param {number} [page=1]
* @returns {object} Tmdb response * @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) 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('query', query)
url.searchParams.append('page', page) url.searchParams.append('page', page)
url.searchParams.append('adult', adult)
const headers = { authorization: localStorage.getItem('token') } const headers = { authorization: localStorage.getItem('token') }
@@ -424,6 +447,7 @@ const elasticSearchMoviesAndShows = (query) => {
export { export {
getMovie, getMovie,
getShow, getShow,
getPerson,
getTmdbMovieListByName, getTmdbMovieListByName,
searchTmdb, searchTmdb,
getUserRequests, getUserRequests,

View File

@@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<list-header :title="listTitle" :info="resultCount" :sticky="true" /> <list-header :title="listTitle" :info="info" :sticky="true" />
<results-list :results="results" v-if="results" /> <results-list :results="results" v-if="results" />
@@ -30,7 +30,8 @@ export default {
results: [], results: [],
page: 1, page: 1,
totalPages: 0, totalPages: 0,
totalResults: 0 totalResults: 0,
loading: true
} }
}, },
computed: { computed: {
@@ -42,18 +43,24 @@ export default {
console.log('routelistname', routeListName) console.log('routelistname', routeListName)
return routeListName.includes('_') ? routeListName.split('_').join(' ') : routeListName return routeListName.includes('_') ? routeListName.split('_').join(' ') : routeListName
}, },
resultCount() { info() {
if (this.results.length === 0) if (this.results.length === 0)
return '' return [null, null]
return [this.pageCount, this.resultCount]
},
resultCount() {
const loadedResults = this.results.length const loadedResults = this.results.length
const totalResults = this.totalResults < 10000 ? this.totalResults : '∞' const totalResults = this.totalResults < 10000 ? this.totalResults : '∞'
return `${loadedResults} of ${totalResults} results` return `${loadedResults} of ${totalResults} results`
},
pageCount() {
return `Page ${this.page} of ${this.totalPages}`
} }
}, },
methods: { methods: {
loadMore() { loadMore() {
console.log(this.$route) console.log(this.$route)
this.loading = true;
this.page++ this.page++
window.history.replaceState({}, 'search', `/#/${this.$route.fullPath}?page=${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 // TODO handle if list is not found
console.log('404 this is not a tmdb list') console.log('404 this is not a tmdb list')
} }
this.loading = false
} }
}, },
created() { created() {

View File

@@ -123,7 +123,7 @@ import SidebarListElement from './ui/sidebarListElem'
import store from '@/store' import store from '@/store'
import LoadingPlaceholder from './ui/LoadingPlaceholder' import LoadingPlaceholder from './ui/LoadingPlaceholder'
import { getMovie, getShow, request, getRequestStatus } from '@/api' import { getMovie, getPerson, getShow, request, getRequestStatus } from '@/api'
export default { export default {
props: ['id', 'type'], props: ['id', 'type'],
@@ -140,7 +140,7 @@ export default {
matched: false, matched: false,
userLoggedIn: storage.sessionId ? true : false, userLoggedIn: storage.sessionId ? true : false,
requested: false, requested: false,
admin: localStorage.getItem('admin'), admin: localStorage.getItem('admin') == "true" ? true : false,
showTorrents: false, showTorrents: false,
compact: false compact: false
} }
@@ -203,6 +203,12 @@ export default {
.catch(error => { .catch(error => {
this.$router.push({ name: '404' }); 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 { } else {
getShow(this.id) getShow(this.id)
.then(this.parseResponse) .then(this.parseResponse)

View File

@@ -13,7 +13,7 @@
</div> </div>
</figure> </figure>
<div class="movies-item__content"> <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> <p class="movies-item__title">{{ movie.year }}</p>
</div> </div>
</a> </a>

View File

@@ -8,10 +8,26 @@
<seasoned-button @click="loadMore">load more</seasoned-button> <seasoned-button @click="loadMore">load more</seasoned-button>
</div> </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> </div>
</template> </template>
<style lang="scss" scoped>
.notFound {
display: flex;
justify-content: center;
align-items: center;
&-title {
font-weight: 400;
}
}
</style>
<script> <script>
import { searchTmdb } from '@/api' import { searchTmdb } from '@/api'
import ListHeader from '@/components/ListHeader' import ListHeader from '@/components/ListHeader'
@@ -37,6 +53,8 @@ export default {
query: String, query: String,
title: String, title: String,
page: Number, page: Number,
adult: undefined,
mediaType: null,
totalPages: 0, totalPages: 0,
results: [], results: [],
totalResults: [] totalResults: []
@@ -50,8 +68,8 @@ export default {
} }
}, },
methods: { methods: {
search(query=this.query, page=this.page) { search(query=this.query, page=this.page, adult=this.adult, mediaType=this.mediaType) {
searchTmdb(query, page) searchTmdb(query, page, adult, mediaType)
.then(this.parseResponse) .then(this.parseResponse)
}, },
parseResponse(data) { parseResponse(data) {
@@ -74,14 +92,16 @@ export default {
} }
}, },
created() { created() {
const { query, page } = this.$route.query const { query, page, adult, media_type } = this.$route.query
if (!query) { if (!query) {
// abort // abort
console.error('abort, no query') console.error('abort, no query')
} }
this.query = decodeURIComponent(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.title = `Search results: ${this.query}`
this.search() this.search()

View File

@@ -20,9 +20,11 @@
<div v-if="listLoaded"> <div v-if="listLoaded">
<div v-if="torrents.length > 0"> <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> <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> <table>
@@ -97,9 +99,10 @@ import { searchTorrents, addMagnet } from '@/api'
import SeasonedButton from '@/components/ui/SeasonedButton' import SeasonedButton from '@/components/ui/SeasonedButton'
import SeasonedInput from '@/components/ui/SeasonedInput' import SeasonedInput from '@/components/ui/SeasonedInput'
import ToggleButton from '@/components/ui/ToggleButton'
export default { export default {
components: { SeasonedButton, SeasonedInput }, components: { SeasonedButton, SeasonedInput, ToggleButton },
props: { props: {
query: { query: {
type: String, type: String,
@@ -110,7 +113,7 @@ export default {
require: true require: true
}, },
tmdb_type: String, tmdb_type: String,
admin: String, admin: Boolean,
show: Boolean show: Boolean
}, },
data() { data() {
@@ -133,6 +136,11 @@ export default {
} }
store.dispatch('torrentModule/reset') store.dispatch('torrentModule/reset')
}, },
watch: {
selectedRelaseType: function(newValue) {
this.applyFilter(newValue)
}
},
methods: { methods: {
selectedSortableClass(headerName) { selectedSortableClass(headerName) {
return headerName === this.prevCol ? 'active' : '' return headerName === this.prevCol ? 'active' : ''
@@ -147,27 +155,31 @@ export default {
expand(event, name) { expand(event, name) {
const existingExpandedElement = document.getElementsByClassName('expanded')[0] const existingExpandedElement = document.getElementsByClassName('expanded')[0]
const clickedElement = event.target.parentNode;
const scopedStyleDataVariable = Object.keys(clickedElement.dataset)[0]
if (existingExpandedElement) { if (existingExpandedElement) {
console.log('exists')
const expandedSibling = event.target.parentNode.nextSibling.className === 'expanded' const expandedSibling = event.target.parentNode.nextSibling.className === 'expanded'
existingExpandedElement.remove() existingExpandedElement.remove()
const table = document.getElementsByTagName('table')[0]
table.style.display = 'block'
if (expandedSibling) { if (expandedSibling) {
console.log('sibling is here')
return return
} }
} }
console.log('expand event', event)
const nameRow = document.createElement('tr') const nameRow = document.createElement('tr')
const nameCol = document.createElement('td') const nameCol = document.createElement('td')
nameRow.className = 'expanded' nameRow.className = 'expanded'
nameRow.dataset[scopedStyleDataVariable] = "";
nameCol.innerText = name nameCol.innerText = name
nameCol.dataset[scopedStyleDataVariable] = "";
nameRow.appendChild(nameCol) nameRow.appendChild(nameCol)
event.target.parentNode.insertAdjacentElement('afterend', nameRow) clickedElement.insertAdjacentElement('afterend', nameRow)
}, },
sendTorrent(magnet, name, event){ sendTorrent(magnet, name, event){
this.$notifications.info({ this.$notifications.info({
@@ -177,7 +189,6 @@ export default {
}) })
event.target.parentNode.classList.add('active') event.target.parentNode.classList.add('active')
addMagnet(magnet, name, this.tmdb_id) addMagnet(magnet, name, this.tmdb_id)
.catch((resp) => { console.log('error:', resp.data) }) .catch((resp) => { console.log('error:', resp.data) })
.then((resp) => { .then((resp) => {
@@ -193,7 +204,6 @@ export default {
if (this.prevCol === col && sameDirection === false) { if (this.prevCol === col && sameDirection === false) {
this.direction = !this.direction this.direction = !this.direction
} }
console.log('col and more', col, sameDirection)
switch (col) { switch (col) {
case 'name': case 'name':
@@ -279,14 +289,13 @@ export default {
@import "./src/scss/variables"; @import "./src/scss/variables";
.expanded { .expanded {
display: flex; display: flex;
margin: 0 1rem; padding: 0.25rem 1rem;
max-width: 100%; max-width: 100%;
border-left: 1px solid $text-color; border-left: 1px solid $text-color;
border-right: 1px solid $text-color; border-right: 1px solid $text-color;
border-bottom: 1px solid $text-color; border-bottom: 1px solid $text-color;
td { td {
// border-left: 1px solid $c-dark;
word-break: break-all; word-break: break-all;
padding: 0.5rem 0.15rem; padding: 0.5rem 0.15rem;
width: 100%; width: 100%;
@@ -298,8 +307,14 @@ export default {
@import "./src/scss/media-queries"; @import "./src/scss/media-queries";
@import "./src/scss/elements"; @import "./src/scss/elements";
.toggle {
max-width: unset !important;
margin: 1rem 0;
}
.container { .container {
background-color: $background-color; background-color: $background-color;
padding: 0 1rem;
} }
.torrentHeader { .torrentHeader {
@@ -348,7 +363,6 @@ table {
.table__content, .table__header { .table__content, .table__header {
display: flex; display: flex;
padding: 0; padding: 0;
margin: 0 1rem;
border-left: 1px solid $text-color; border-left: 1px solid $text-color;
border-right: 1px solid $text-color; border-right: 1px solid $text-color;
border-bottom: 1px solid $text-color; border-bottom: 1px solid $text-color;

View File

@@ -70,7 +70,7 @@ export default {
.message { .message {
width: 100%; width: 100%;
max-width: 35rem; max-width: 35rem;
height: 75px; min-height: 75px;
display: flex; display: flex;
margin-top: 1rem; margin-top: 1rem;

View File

@@ -11,13 +11,19 @@ export default {
data() { data() {
return { return {
darkmode: window.getComputedStyle(document.body).colorScheme.includes('dark') darkmode: this.supported
} }
}, },
methods: { methods: {
toggleDarkmode() { toggleDarkmode() {
this.darkmode = !this.darkmode; this.darkmode = !this.darkmode;
document.body.className = this.darkmode ? 'dark' : 'light' 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: { computed: {
@@ -41,7 +47,7 @@ export default {
margin-right: 2px; margin-right: 2px;
bottom: 0; bottom: 0;
right: 0; right: 0;
z-index: 1; z-index: 10;
-webkit-user-select: none; -webkit-user-select: none;
-moz-user-select: none; -moz-user-select: none;

View File

@@ -1,16 +1,18 @@
<template> <template>
<div> <div>
<a @click="$emit('click')"><li> <a @click="$emit('click')">
<li>
<figure :class="activeClassIfActive"> <figure :class="activeClassIfActive">
<svg><use :xlink:href="iconRefNameIfActive"/></svg> <svg class="icon"><use :xlink:href="iconRefNameIfActive"/></svg>
</figure> </figure>
<span :class="activeClassIfActive">{{ contentTextToDisplay }}</span> <span class="text" :class="activeClassIfActive">{{ contentTextToDisplay }}</span>
<span v-if="supplementaryText" class="supplementary-text"> <span v-if="supplementaryText" class="supplementary-text">
{{ supplementaryText }} {{ supplementaryText }}
</span> </span>
</li></a> </li>
</a>
</div> </div>
</template> </template>
@@ -44,7 +46,7 @@ export default {
iconRefNameIfActive() { iconRefNameIfActive() {
const { iconRefActive, iconRef, active } = this const { iconRefActive, iconRef, active } = this
if ((iconRefActive && iconRef) & active) { if ((iconRefActive && iconRef) && active) {
return iconRefActive return iconRefActive
} }
return iconRef return iconRef
@@ -85,37 +87,51 @@ li {
&:hover { &:hover {
color: $text-color-70; color: $text-color-70;
cursor: pointer; cursor: pointer;
.icon {
fill: $text-color-70;
cursor: pointer;
transform: scale(1.1, 1.1);
}
} }
.active { .active {
color: $text-color; color: $text-color;
.icon {
fill: $green;
}
} }
.pending { .pending {
color: #f8bd2d; color: #f8bd2d;
} }
.text {
margin-left: 26px;
}
.supplementary-text { .supplementary-text {
flex-grow: 1; flex-grow: 1;
text-align: right; text-align: right;
} }
figure, figure > svg { figure {
width: 18px; position: absolute;
height: 18px;
> svg {
position: relative;
top: 50%;
width: 16px;
height: 16px;
margin: 0 7px 0 0; margin: 0 7px 0 0;
fill: $text-color-50; fill: $text-color-50;
transition: fill 0.5s ease, transform 0.5s ease; transition: fill 0.5s ease, transform 0.5s ease;
& .waiting { & .waiting {
transform: scale(0.8, 0.8); transform: scale(0.8, 0.8);
} }
& .pending { & .pending {
fill: #f8bd2d; fill: #f8bd2d;
} }
&:hover &-icon {
fill: $text-color-70;
cursor: pointer;
}
&.active > svg {
fill: $green;
} }
} }
} }

View File

@@ -5,6 +5,31 @@ $tablet-p-width: 768px;
$tablet-l-width: 1024px; $tablet-l-width: 1024px;
$desktop-width: 1200px; $desktop-width: 1200px;
$desktop-l-width: 1600px; $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 // Media
@mixin mobile-only{ @mixin mobile-only{

View File

@@ -15,8 +15,8 @@
--background-95: rgba(255, 255, 255, 0.95); --background-95: rgba(255, 255, 255, 0.95);
--background-70: rgba(255, 255, 255, 0.7); --background-70: rgba(255, 255, 255, 0.7);
--background-40: rgba(255, 255, 255, 0.4); --background-40: rgba(255, 255, 255, 0.4);
--background-nav-logo: #081c24;
--background-nav-logo: #081c24;
--color-green: #01d277; --color-green: #01d277;
--color-green-90: rgba(1, 210, 119, .9); --color-green-90: rgba(1, 210, 119, .9);
--color-green-70: rgba(1, 210, 119, .73); --color-green-70: rgba(1, 210, 119, .73);
@@ -44,12 +44,12 @@
--text-color-50: rgba(255, 255, 255, 0.5); --text-color-50: rgba(255, 255, 255, 0.5);
--text-color-5: rgba(255, 255, 255, 0.05); --text-color-5: rgba(255, 255, 255, 0.05);
--text-color-secondary: orange; --text-color-secondary: orange;
--background-color: #1e1f22; --background-color: rgba(17, 17, 17, 1);
--background-color-secondary: #111111; --background-color-secondary: rgba(6, 7, 8, 1);
--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-ui: #202125; --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-50: rgba(255, 255, 255, 0.5);
--text-color-5: rgba(255, 255, 255, 0.05); --text-color-5: rgba(255, 255, 255, 0.05);
--text-color-secondary: orange; --text-color-secondary: orange;
--background-color: #1e1f22; --background-color: rgba(17, 17, 17, 1);
--background-color-secondary: #111111; --background-color-secondary: rgba(6, 7, 8, 1);
--background-95: rgba(30, 31, 34, 0.95);
--background-70: rgba(30, 31, 34, 0.7);
--background-ui: #202125; --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 { .light {
@@ -117,14 +117,11 @@ $color-error-highlight: var(--color-error-highlight) !default;
--text-color-70: rgba(8, 28, 36, 0.7); --text-color-70: rgba(8, 28, 36, 0.7);
--text-color-50: rgba(8, 28, 36, 0.5); --text-color-50: rgba(8, 28, 36, 0.5);
--text-color-5: rgba(8, 28, 36, 0.05); --text-color-5: rgba(8, 28, 36, 0.05);
--text-color-inverted: #fff;
--text-color-secondary: orange; --text-color-secondary: orange;
--background-color: #f8f8f8; --background-color: #f8f8f8;
--background-color-secondary: #ffffff; --background-color-secondary: #ffffff;
--background-ui: #edeef0;
--background-95: rgba(255, 255, 255, 0.95); --background-95: rgba(255, 255, 255, 0.95);
--background-70: rgba(255, 255, 255, 0.7); --background-70: rgba(255, 255, 255, 0.7);
--background-ui: #edeef0; --background-40: rgba(255, 255, 255, 0.4);
--background-nav-logo: #081c24;
--color-green: #01d277;
--color-teal: #091c24;
} }