<!-- - @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"> {{ t('podcast', 'Duration') }} </th> <th class="dateColumn"> {{ t('podcast', 'Date') }} </th> </tr> </thead> <tbody> <tr v-for="(episode, idx) in episodes" :key="idx" :class="{ selected: idx === activeItem}"> <td class="iconColumn"> <div> <blur-hash-image hash="00PZr%" :src="episode.imgURL" /> </div> </td> <td class="nameColumn" @click="changeRoute(`/#/browse/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(`/#/browse/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(`/#/browse/show/${episode.podcast_id}/${episode.id}`)"> {{ episode.duration_string }} </td> <td class="dateColumn" @click="changeRoute(`/#/browse/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; } th.durationColumn { width: 90px; } th.dateColumn { width: 130px; } } 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: 35px; div { width: 74px; height: 74px; } } 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>