nextcloud-app-radio/src/components/Table.vue
2020-11-24 15:16:53 +01:00

276 lines
5.6 KiB
Vue

<!--
- @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('radio', 'Name') }}
</th>
<th class="actionColumn" />
</tr>
</thead>
<tbody>
<template v-if="!isFolder">
<tr
v-for="(station, idx) in stationData"
:key="idx"
:class="{ selected: idx === activeItem}">
<td @click="doPlay(idx, station)">
<blur-hash-image
class="stationIcon"
width="32"
height="32"
:hash="station.blurHash"
:src="station.favicon" />
<span :class="{ 'icon-starred': favorites.flat().includes(station.stationuuid) }" />
</td>
<td class="nameColumn" @click="doPlay(idx, station)">
<span class="innernametext">
{{ station.name }}
</span>
</td>
<td class="actionColumn">
<Actions>
<ActionButton
v-if="!favorites.flat().includes(station.stationuuid)"
icon="icon-star"
:close-after-click="true"
@click="doFavor(idx, station)">
{{ t('radio', 'Add to favorites') }}
</ActionButton>
<ActionButton
v-if="favorites.flat().includes(station.stationuuid)"
icon="icon-star"
:close-after-click="true"
@click="doFavor(idx, station)">
{{ t('radio', 'Remove from favorites') }}
</ActionButton>
<ActionButton
icon="icon-info"
:close-after-click="true"
@click="toggleSidebar(station)">
{{ t('radio', 'Details') }}
</ActionButton>
</Actions>
</td>
</tr>
</template>
<template v-if="isFolder">
<tr
v-for="(station, idx) in stationData"
:key="idx"
@click="changeRoute(station.path)">
<td>
<span class="icon-folder" />
</td>
<td class="nameColumn">
<span class="innernametext">
{{ station.name }}
</span>
</td>
<td class="actionColumn" />
</tr>
</template>
</tbody>
</table>
</template>
<script>
import Actions from '@nextcloud/vue/dist/Components/Actions'
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
export default {
name: 'Table',
components: {
Actions,
ActionButton,
},
props: {
favorites: {
type: Array,
default() { return [] },
},
stationData: {
type: Array,
default() { return [] },
},
},
data: () => ({
activeItem: null,
}),
computed: {
isFolder() {
if (this.stationData[0]) {
if (this.stationData[0].type === 'folder') {
return true
}
}
return false
},
},
methods: {
doPlay(idx, station) {
this.activeItem = idx
this.$emit('doPlay', station)
},
doFavor(idx, station) {
this.$emit('doFavor', station)
},
toggleSidebar(station) {
this.$emit('toggleSidebar', station)
},
changeRoute(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;
}
th, th a {
color: var(--color-text-maxcontrast);
}
th.iconColumn {
padding: 0px;
width: 72px;
}
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;
span.icon-folder {
display: block;
background-size: cover;
width: 30px;
height: 30px;
}
}
tr {
height: 51px;
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);
}
tr td:first-child {
padding-left: 40px;
width: 32px;
padding-right: 0px;
}
td.nameColumn {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding-right: 0px;
}
td.nameColumn .innernametext {
color: var(--color-main-text);
position: relative;
vertical-align: top;
user-select: none;
cursor: pointer;
}
.icon-starred {
background-image: var(--icon-star-dark-fc0);
background-size: 16px 16px;
background-repeat: no-repeat;
background-position: center;
min-width: 16px;
min-height: 16px;
right: -7px;
top: -38px;
margin-bottom: -38px;
float: right;
position: relative;
pointer-events: none;
}
}
}
</style>