Forked from
onny / nextcloud-app-podcast
151 commits behind the upstream repository.
Table.vue 6.17 KiB
<!--
- @copyright Copyright (c) 2020 Jonas Heinrich
-
- @author Jonas Heinrich <onny@project-insanity.org>
-
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-->
<template>
<table>
<thead>
<tr>
<th class="iconColumn" />
<th class="nameColumn">
{{ t('podcast', 'Name') }}
</th>
<th class="actionColumn" />
<th class="durationColumn" style="width: 90px">
{{ t('podcast', 'Duration') }}
</th>
<th class="dateColumn" style="width: 130px">
{{ t('podcast', 'Date') }}
</th>
</tr>
</thead>
<tbody>
<tr
v-for="(episode, idx) in episodes"
:key="idx"
:class="{ selected: idx === activeItem}">
<td class="iconColumn">
<div style="width: 64px; height: 64px;">
<blur-hash-image
hash="L1TSUA?bj[?b~qfQfQj[ayfQfQfQ"
:src="episode.imgURL" />
</div>
</td>
<td
class="nameColumn"
@click="changeRoute(`/#/show/${episode.podcast_id}/${episode.id}`)">
<b>{{ episode.title }}</b>
<vue-show-more-text
:text="escapedEpisodeDescription(episode.description)"
:lines="2"
:has-more="false"
additional-container-css="padding: 0px;" />
</td>
<td class="actionColumn">
<Actions>
<ActionButton
icon="icon-play"
:close-after-click="true"
@click="doPlay(idx, episode)">
{{ t('podcast', 'Play') }}
</ActionButton>
<ActionButton
icon="icon-info"
:close-after-click="true"
@click="changeRoute(`/#/show/${episode.podcast_id}/${episode.id}`)">
{{ t('podcast', 'Show') }}
</ActionButton>
<ActionButton
icon="icon-download"
:close-after-click="true"
@click="downloadFile(episode.enclosure)">
{{ t('podcast', 'Download') }}
</ActionButton>
<ActionButton
icon="icon-shared"
:close-after-click="true">
{{ t('podcast', 'Share') }}
</ActionButton>
</Actions>
</td>
<td
class="durationColumn"
@click="changeRoute(`/#/show/${episode.podcast_id}/${episode.id}`)">
{{ episode.duration_string }}
</td>
<td
class="dateColumn"
@click="changeRoute(`/#/show/${episode.podcast_id}/${episode.id}`)">
{{ readableTime(episode.inserted) }}
</td>
</tr>
</tbody>
</table>
</template>
<script>
import Actions from '@nextcloud/vue/dist/Components/Actions'
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
import TimeAgo from 'javascript-time-ago'
import en from 'javascript-time-ago/locale/en'
import vueShowMoreText from 'vue-show-more-text'
TimeAgo.addDefaultLocale(en)
const timeAgo = new TimeAgo('en-US')
export default {
name: 'Table',
components: {
Actions,
ActionButton,
vueShowMoreText,
},
props: {
episodes: {
type: Array,
default() { return [] },
},
},
data: () => ({
activeItem: null,
}),
methods: {
escapedEpisodeDescription(episodeDescription) {
episodeDescription = episodeDescription.replace(/\n/g, '')
return episodeDescription
},
readableTime(datetime) {
return timeAgo.format(Date.parse(datetime), 'twitter-minute-now')
},
downloadFile(episodeURL) {
window.open(episodeURL, 'download')
},
doPlay(idx, episode) {
this.activeItem = idx
this.$emit('doPlay', episode)
},
changeRoute(path) {
console.log(path)
this.$router.push({ path })
},
},
}
</script>
<style lang="scss">
/* Workaround wrong positioning
actions popover menu
https://github.com/nextcloud/nextcloud-vue/issues/1384 */
body {
min-height: 100%;
height: auto;
}
table {
width: 100%;
min-width: 250px;
table-layout:fixed;
position: relative;
thead {
background-color: var(--color-main-background-translucent);
z-index: 60;
position: sticky;
top: 50px;
th {
border-bottom: 1px solid var(--color-border);
padding: 15px;
height: 50px;
color: var(--color-text-maxcontrast);
}
th.iconColumn {
padding: 0px;
width: 115px;
}
th.nameColumn {
width: 100%;
}
th.actionColumn {
width: 72px;
}
}
tbody {
td {
padding: 0 15px;
font-style: normal;
background-position: 8px center;
background-repeat: no-repeat;
border-bottom: 1px solid var(--color-border);
cursor: pointer;
}
tr {
height: 91px;
background-color: var(--color-background-light);
transition: opacity 500ms ease 0s;
tr:hover, tr:focus, tr.mouseOver td {
background-color: var(--color-background-hover);
}
}
tr td * {
cursor: pointer;
}
tr.selected {
background-color: var(--color-primary-light);
}
td.iconColumn {
padding-right: 0px;
padding-left: 40px;
}
td.nameColumn {
overflow: hidden;
text-overflow: ellipsis;
padding-right: 0px;
}
td.nameColumn b {
color: var(--color-main-text);
user-select: none;
cursor: pointer;
font-size: 1.1em;
}
td.nameColumn span {
display: block;
max-height: 45px;
white-space: normal;
text-overflow: ellipsis;
overflow: hidden;
color: #657786;
}
}
}
@media only screen and (max-width: 500px) {
table {
thead {
th.iconColumn {
width: 85px;
}
th.nameColumn {
padding-left: 0px;
}
th.actionColumn {
padding-left: 5px;
padding-right: 5px;
width: 50px;
}
th.durationColumn, th.dateColumn {
display: none;
}
}
tbody {
td.iconColumn {
padding-left: 10px;
}
td.nameColumn {
padding-left: 0px;
}
td.actionColumn {
padding-left: 5px;
padding-right: 5px;
width: 50px;
}
td.durationColumn, td.dateColumn {
display: none;
}
}
}
}
</style>