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 })
}
/**
* 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,

View File

@@ -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() {

View File

@@ -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)

View File

@@ -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>

View File

@@ -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()

View File

@@ -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;

View File

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

View File

@@ -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;

View File

@@ -1,16 +1,18 @@
<template>
<div>
<a @click="$emit('click')"><li>
<figure :class="activeClassIfActive">
<svg><use :xlink:href="iconRefNameIfActive"/></svg>
</figure>
<a @click="$emit('click')">
<li>
<figure :class="activeClassIfActive">
<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>
<span v-if="supplementaryText" class="supplementary-text">
{{ supplementaryText }}
</span>
</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;
margin: 0 7px 0 0;
fill: $text-color-50;
transition: fill 0.5s ease, transform 0.5s ease;
&.waiting {
transform: scale(0.8, 0.8);
}
&.pending {
fill: #f8bd2d;
}
&:hover &-icon {
fill: $text-color-70;
cursor: pointer;
}
&.active > svg {
fill: $green;
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 {
transform: scale(0.8, 0.8);
}
& .pending {
fill: #f8bd2d;
}
}
}
}

View File

@@ -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{

View File

@@ -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;
--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);
}