new and improved episodes page

pull/67/head
Akhil Gupta 4 years ago
parent d4bb3d8665
commit 80bbce66d2

@ -53,7 +53,12 @@
} }
body.playerExists .button-enqueue{ body.playerExists .button-enqueue{
display: inline-block; display: inline-block;
[v-cloak] {
display: none;
}
} }
</style> </style>
</head> </head>
<body> <body>
@ -62,10 +67,13 @@
<br />{{$setting := .setting}} <br />{{$setting := .setting}}
<div id="app"> <div id="app" v-cloak>
<form @submit.prevent="submitFilters()"> <button @click="toggleFilters()" class="u-full-width">
<span v-show="!showFilters">Show Filters</span>
<span v-show="showFilters">Hide Filters</span>
</button>
<form @submit.prevent="submitFilters()" v-show="showFilters">
<div class="row"> <div class="row">
<input class="columns five" type="search" @input="searchQueryUpated()" v-model="filter.q" placeholder="Search"> <input class="columns five" type="search" @input="searchQueryUpated()" v-model="filter.q" placeholder="Search">
<div class="columns three"> <vue-multiselect v-model="selectedSorting" :options="sortOptions" :searchable="false" <div class="columns three"> <vue-multiselect v-model="selectedSorting" :options="sortOptions" :searchable="false"
@ -75,32 +83,35 @@
<div class="columns one"> <vue-multiselect :show-pointer="false" v-model="filter.count" :options="pagingOptions" :searchable="false" :allow-empty="false" :close-on-select="true" :show-labels="false" placeholder="Pick a value"></vue-multiselect> <div class="columns one"> <vue-multiselect :show-pointer="false" v-model="filter.count" :options="pagingOptions" :searchable="false" :allow-empty="false" :close-on-select="true" :show-labels="false" placeholder="Pick a value"></vue-multiselect>
</div> </div>
<div class="columns three"> <div class="columns three"> <vue-multiselect v-model="selectedPlayedStatus" :options="playedStatusOptions" :searchable="false"
<input type="submit" value="Filter" class="button"> :multiple="false" :close-on-select="true" :clear-on-select="true" :allow-empty="false" :show-labels="false"
<button class="button" @click="resetFilters()">Reset</button> placeholder="Sort By" label="Label" track-by="Value" :preselect-first="true">
</div> </vue-multiselect></div>
</div> </div>
<div class="row"> <div class="row">
<vue-multiselect class="columns three" v-model="selectedPodcasts" :options="podcasts" <vue-multiselect class="columns three" v-model="selectedPodcasts" :options="podcasts" :show-labels="false"
:multiple="true" :close-on-select="false" :clear-on-select="false" :multiple="true" :close-on-select="false" :clear-on-select="false"
:preserve-search="true" placeholder="Podcasts" label="Title" track-by="ID" :preselect-first="false"> :preserve-search="true" placeholder="Podcasts" label="Title" track-by="ID" :preselect-first="false">
<template slot="selection" slot-scope="{ values, search, isOpen }"> <template slot="selection" slot-scope="{ values, search, isOpen }">
<span class="multiselect__single" v-if="values.length && !isOpen">${ values.length } options selected</span> <span class="multiselect__single" v-if="values.length && !isOpen">${ values.length } options selected</span>
</template> </template>
</vue-multiselect> </vue-multiselect>
<vue-multiselect class="columns three" v-model="selectedTags" :options="tags" :multiple="true" :close-on-select="false" :clear-on-select="false" :preserve-search="true" placeholder="Tags" label="Label" track-by="ID" :preselect-first="false"> <vue-multiselect class="columns three" v-model="selectedTags" :show-labels="false" :options="tags" :multiple="true" :close-on-select="false" :clear-on-select="false" :preserve-search="true" placeholder="Tags" label="Label" track-by="ID" :preselect-first="false">
<template slot="selection" slot-scope="{ values, search, isOpen }"><span class="multiselect__single" v-if="values.length && !isOpen">${ values.length } options selected</span></template> <template slot="selection" slot-scope="{ values, search, isOpen }"><span class="multiselect__single" v-if="values.length && !isOpen">${ values.length } options selected</span></template>
</vue-multiselect> </vue-multiselect>
<div class="columns three"> <vue-multiselect v-model="selectedDownloadStatus" :options="downloadStatusOptions" :searchable="false" <div class="columns three"> <vue-multiselect v-model="selectedDownloadStatus" :options="downloadStatusOptions" :searchable="false"
:multiple="false" :close-on-select="true" :clear-on-select="true" :allow-empty="false" :show-labels="false" :multiple="false" :close-on-select="true" :clear-on-select="true" :allow-empty="false" :show-labels="false"
placeholder="Sort By" label="Label" track-by="Value" :preselect-first="true"> placeholder="Sort By" label="Label" track-by="Value" :preselect-first="true">
</vue-multiselect></div> </vue-multiselect></div>
<div class="columns three"> <vue-multiselect v-model="selectedPlayedStatus" :options="playedStatusOptions" :searchable="false" <div class="columns three">
:multiple="false" :close-on-select="true" :clear-on-select="true" :allow-empty="false" :show-labels="false" <a title="Play items in this page" v-if="podcastItems.length" class="button" @click="playPage()"><i class="fas fa-play"></i></a>
placeholder="Sort By" label="Label" track-by="Value" :preselect-first="true"> <a title="Enqueue items in this page" v-if="podcastItems.length" class="button button-enqueue" @click="enqueuePage()"><i class="fas fa-plus"></i></a>
</vue-multiselect></div> <a title="Reset Filters" class="button" @click="resetFilters()"><i class="fas fa-undo"></i></a>
</div>
</div> </div>
</form> </form>
<hr> <hr>
@ -275,10 +286,17 @@ var app = new Vue({
computed:{ computed:{
page(){ page(){
return this.filter.page; return this.filter.page;
},
count(){
return this.filter.count;
} }
}, },
watch:{ watch:{
page(newPage,oldPage){ page(newPage,oldPage){
if(newPage==oldPage){
return;
}
if(newPage==1){ if(newPage==1){
this.filter.previousPage=0; this.filter.previousPage=0;
}else{ }else{
@ -292,6 +310,17 @@ var app = new Vue({
this.getData() this.getData()
}, },
count(current,old){
this.getData()
},
showFilters(current,old){
if(localStorage){
localStorage.showFilters=current
}
},
selectedPodcasts(current,old){ selectedPodcasts(current,old){
var arr=[]; var arr=[];
for (let index = 0; index < current.length; index++) { for (let index = 0; index < current.length; index++) {
@ -299,7 +328,7 @@ var app = new Vue({
arr.push(element.ID); arr.push(element.ID);
} }
this.filter['podcastIds']=arr; this.filter['podcastIds']=arr;
this.getData() this.submitFilters()
}, },
selectedTags(current,old){ selectedTags(current,old){
var arr=[]; var arr=[];
@ -308,25 +337,28 @@ var app = new Vue({
arr.push(element.ID); arr.push(element.ID);
} }
this.filter['tagIds']=arr; this.filter['tagIds']=arr;
this.getData() this.submitFilters()
}, },
selectedSorting(current,old){ selectedSorting(current,old){
this.filter.sorting=current.Value; this.filter.sorting=current.Value;
this.getData() this.submitFilters()
}, },
selectedDownloadStatus(current,old){ selectedDownloadStatus(current,old){
this.filter.isDownloaded=current.Value; this.filter.isDownloaded=current.Value;
this.getData() this.submitFilters()
}, },
selectedPlayedStatus(current,old){ selectedPlayedStatus(current,old){
this.filter.isPlayed=current.Value; this.filter.isPlayed=current.Value;
this.getData() this.submitFilters()
}, },
}, },
mounted(){ mounted(){
if(localStorage && localStorage.episodesFilter){ if(localStorage && localStorage.episodesFilter){
this.filter=JSON.parse(localStorage.episodesFilter); this.filter=JSON.parse(localStorage.episodesFilter);
} }
if(localStorage && localStorage.showFilters){
this.showFilters=JSON.parse(localStorage.showFilters);
}
if(this.filter.podcastIds!=null){ if(this.filter.podcastIds!=null){
var selectedPodcasts=[]; var selectedPodcasts=[];
@ -425,15 +457,17 @@ var app = new Vue({
downloadToDisk(item.ID) downloadToDisk(item.ID)
}, },
openPlayer(item){ openPlayer(item){
openPlayer(item.ID) openPlayer([item.ID])
}, },
enqueuePlayer(item){ enqueueEpisode(item){
enqueuePlayer(item.ID) enqueueEpisode([item.ID])
}, },
searchQueryUpated(){ searchQueryUpated(){
var self=this; var self=this;
clearTimeout(this.debounce) clearTimeout(this.debounce)
this.debounce = setTimeout(() => { this.debounce = setTimeout(() => {
self.filter.page=1
self.getData() self.getData()
}, 600) }, 600)
}, },
@ -447,6 +481,23 @@ var app = new Vue({
this.getData(); this.getData();
}, },
toggleFilters(){
this.showFilters=!this.showFilters
},
playPage(){
var itemIds=[];
for(var i=0;i<this.podcastItems.length;i++){
itemIds.push(this.podcastItems[i].ID)
}
openPlayer(itemIds)
},
enqueuePage(){
var itemIds=[];
for(var i=0;i<this.podcastItems.length;i++){
itemIds.push(this.podcastItems[i].ID)
}
enqueueEpisode(itemIds)
},
updateUrl(){ updateUrl(){
var url= new URL(window.top.location.href); var url= new URL(window.top.location.href);
var copy= Vue.util.extend({},this.filter); var copy= Vue.util.extend({},this.filter);
@ -479,6 +530,7 @@ var app = new Vue({
self.filter=response.data.filter; self.filter=response.data.filter;
self.saveFilter(self.filter); self.saveFilter(self.filter);
self.updateUrl(); self.updateUrl();
setPageTitle("Episodes ("+self.filter.totalCount+")")
}) })
.catch(function (error) { .catch(function (error) {
if (error.response && error.response.data && error.response.data.message) { if (error.response && error.response.data && error.response.data.message) {
@ -505,6 +557,7 @@ var app = new Vue({
selectedTags:[], selectedTags:[],
selectedDownloadStatus:"", selectedDownloadStatus:"",
selectedPlayedStatus:"", selectedPlayedStatus:"",
showFilters:localStorage && JSON.parse(localStorage.showFilters),
{{ $len := len .podcastItems}} {{ $len := len .podcastItems}}
podcastItems: {{if gt $len 0}} {{ .podcastItems }} {{else}} [] {{end}}, podcastItems: {{if gt $len 0}} {{ .podcastItems }} {{else}} [] {{end}},
@ -664,11 +717,11 @@ var app = new Vue({
document.body.classList.add("playerExists") document.body.classList.add("playerExists")
} }
}); });
function enqueueEpisode(id){ function enqueueEpisode(ids){
if(!socket){ if(!socket){
return return
} }
socket.send(getWebsocketMessage("Enqueue",`{"itemId":"${id}"}`)) socket.send(getWebsocketMessage("Enqueue",`{"itemIds":${JSON.stringify(ids)}}`))
} }
function enquePodcast(id){ function enquePodcast(id){
if(!socket){ if(!socket){

@ -141,7 +141,7 @@ div#overlay{
<div></div> <div></div>
<div></div> <div></div>
</a> </a>
<h1>{{ .title }}</h1> <h1 id="pageTitle">{{ .title }}</h1>
{{if .podcastId }} {{if .podcastId }}
<button <button
class="button" class="button"
@ -199,6 +199,11 @@ onclick="enquePodcast({{ .podcastId }})"
<div id="overlay" onclick="toggleMenu()"></div> <div id="overlay" onclick="toggleMenu()"></div>
<script> <script>
function setPageTitle(content){
document.getElementById('pageTitle').innerText=content;
}
function toggleMenu(){ function toggleMenu(){
var sideDrawer= document.getElementById('sideDrawer') var sideDrawer= document.getElementById('sideDrawer')
var overlay= document.getElementById('overlay') var overlay= document.getElementById('overlay')

@ -79,10 +79,12 @@
} }
checkUseMore(); checkUseMore();
function openPlayer(itemId, podcastId,tagIds) { function openPlayer(itemIds, podcastId,tagIds) {
var url = "/player?"; var url = "/player?";
if (itemId) { if(itemIds && itemIds.length>0){
url += "&itemId=" + itemId; for (const itemId of itemIds) {
url += "&itemIds=" + itemId;
}
} }
if (podcastId) { if (podcastId) {
url += "&podcastId=" + podcastId; url += "&podcastId=" + podcastId;

@ -106,11 +106,11 @@ func PodcastPage(c *gin.Context) {
} }
func getItemsToPlay(itemId, podcastId string, tagIds []string) []db.PodcastItem { func getItemsToPlay(itemIds []string, podcastId string, tagIds []string) []db.PodcastItem {
var items []db.PodcastItem var items []db.PodcastItem
if itemId != "" { if len(itemIds) > 0 {
toAdd := service.GetPodcastItemById(itemId) toAdd, _ := service.GetAllPodcastItemsByIds(itemIds)
items = append(items, *toAdd) items = *toAdd
} else if podcastId != "" { } else if podcastId != "" {
pod := service.GetPodcastById(podcastId) pod := service.GetPodcastById(podcastId)
@ -132,16 +132,16 @@ func getItemsToPlay(itemId, podcastId string, tagIds []string) []db.PodcastItem
func PlayerPage(c *gin.Context) { func PlayerPage(c *gin.Context) {
itemId, hasItemId := c.GetQuery("itemId") itemIds, hasItemIds := c.GetQueryArray("itemIds")
podcastId, hasPodcastId := c.GetQuery("podcastId") podcastId, hasPodcastId := c.GetQuery("podcastId")
tagIds, hasTagIds := c.GetQueryArray("tagIds") tagIds, hasTagIds := c.GetQueryArray("tagIds")
title := "Podgrab" title := "Podgrab"
var items []db.PodcastItem var items []db.PodcastItem
var totalCount int64 var totalCount int64
if hasItemId { if hasItemIds {
toAdd := service.GetPodcastItemById(itemId) toAdd, _ := service.GetAllPodcastItemsByIds(itemIds)
items = append(items, *toAdd) items = *toAdd
totalCount = 1 totalCount = int64(len(items))
} else if hasPodcastId { } else if hasPodcastId {
pod := service.GetPodcastById(podcastId) pod := service.GetPodcastById(podcastId)
items = pod.PodcastItems items = pod.PodcastItems

@ -9,7 +9,7 @@ import (
) )
type EnqueuePayload struct { type EnqueuePayload struct {
ItemId string `json:"itemId"` ItemIds []string `json:"itemIds"`
PodcastId string `json:"podcastId"` PodcastId string `json:"podcastId"`
TagIds []string `json:"tagIds"` TagIds []string `json:"tagIds"`
} }
@ -91,7 +91,7 @@ func HandleWebsocketMessages() {
fmt.Println(msg.Payload) fmt.Println(msg.Payload)
err := json.Unmarshal([]byte(msg.Payload), &payload) err := json.Unmarshal([]byte(msg.Payload), &payload)
if err == nil { if err == nil {
items := getItemsToPlay(payload.ItemId, payload.PodcastId, payload.TagIds) items := getItemsToPlay(payload.ItemIds, payload.PodcastId, payload.TagIds)
var player *websocket.Conn var player *websocket.Conn
for connection, id := range activePlayers { for connection, id := range activePlayers {

@ -170,6 +170,22 @@ func GetAllPodcastItemsByPodcastIds(podcastIds []string, podcastItems *[]Podcast
result := DB.Preload(clause.Associations).Where("podcast_id in ?", podcastIds).Order("pub_date desc").Find(&podcastItems) result := DB.Preload(clause.Associations).Where("podcast_id in ?", podcastIds).Order("pub_date desc").Find(&podcastItems)
return result.Error return result.Error
} }
func GetAllPodcastItemsByIds(podcastItemIds []string) (*[]PodcastItem, error) {
var podcastItems []PodcastItem
var sb strings.Builder
sb.WriteString("\n CASE ID \n")
for i, v := range podcastItemIds {
sb.WriteString(fmt.Sprintf("WHEN '%v' THEN %v \n", v, i+1))
}
sb.WriteString(fmt.Sprintln("END"))
result := DB.Debug().Preload(clause.Associations).Where("id in ?", podcastItemIds).Order(sb.String()).Find(&podcastItems)
return &podcastItems, result.Error
}
func SetAllEpisodesToDownload(podcastId string) error { func SetAllEpisodesToDownload(podcastId string) error {
result := DB.Model(PodcastItem{}).Where(&PodcastItem{PodcastID: podcastId, DownloadStatus: Deleted}).Update("download_status", NotDownloaded) result := DB.Model(PodcastItem{}).Where(&PodcastItem{PodcastID: podcastId, DownloadStatus: Deleted}).Update("download_status", NotDownloaded)

@ -59,6 +59,10 @@ func GetPodcastItemById(id string) *db.PodcastItem {
return &podcastItem return &podcastItem
} }
func GetAllPodcastItemsByIds(podcastItemIds []string) (*[]db.PodcastItem, error) {
return db.GetAllPodcastItemsByIds(podcastItemIds)
}
func GetAllPodcastItemsByPodcastIds(podcastIds []string) *[]db.PodcastItem { func GetAllPodcastItemsByPodcastIds(podcastIds []string) *[]db.PodcastItem {
var podcastItems []db.PodcastItem var podcastItems []db.PodcastItem

Loading…
Cancel
Save