Widget.vue 4.89 KB
Newer Older
1
<template>
2
  <div class="wrapper">
3
4
    <h3 class="ui header">
      <slot name="title"></slot>
5
      <span v-if="showCount" class="ui tiny circular label">{{ count }}</span>
6
    </h3>
7
    <slot></slot>
8
9
10
    <button v-if="controls" :disabled="!previousPage" @click="fetchData(previousPage)" :class="['ui', {disabled: !previousPage}, 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'angle left', 'icon']"></i></button>
    <button v-if="controls" :disabled="!nextPage" @click="fetchData(nextPage)" :class="['ui', {disabled: !nextPage}, 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'angle right', 'icon']"></i></button>
    <button v-if="controls" @click="fetchData('albums/')" :class="['ui', 'circular', 'icon', 'basic', 'button']"><i :class="['ui', 'refresh', 'icon']"></i></button>
11
12
13
14
15
16
    <div class="ui hidden divider"></div>
    <div class="ui five cards">
      <div v-if="isLoading" class="ui inverted active dimmer">
        <div class="ui loader"></div>
      </div>
      <div class="card" v-for="album in albums" :key="album.id">
Eliot Berriot's avatar
Eliot Berriot committed
17
        <div :class="['ui', 'image', 'with-overlay', {'default-cover': !album.cover.original}]" v-lazy:background-image="getImageUrl(album)">
18
          <play-button class="play-overlay" :icon-only="true" :is-playable="album.is_playable" :button-classes="['ui', 'circular', 'large', 'orange', 'icon', 'button']" :album="album"></play-button>
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
        </div>
        <div class="content">
          <router-link :title="album.title" :to="{name: 'library.albums.detail', params: {id: album.id}}">
            {{ album.title|truncate(25) }}
          </router-link>
          <div class="description">
            <span>
              <router-link :title="album.artist.name" class="discrete link" :to="{name: 'library.artists.detail', params: {id: album.artist.id}}">
                {{ album.artist.name|truncate(23) }}
              </router-link>
            </span>
          </div>
        </div>
        <div class="extra content">
          <human-date class="left floated" :date="album.creation_date"></human-date>
34
          <play-button class="right floated basic icon" :dropdown-only="true" :is-playable="album.is_playable" :dropdown-icon-classes="['ellipsis', 'horizontal', 'large', 'grey']" :album="album"></play-button>
35
36
37
        </div>
      </div>
    </div>
38
39
40
41
42
43
44
45
    <template v-if="!isLoading && albums.length === 0">
      <div class="ui placeholder segment">
        <div class="ui icon header">
          <i class="compact disc icon"></i>
          No results matching your query
        </div>
      </div>
    </template>
46
47
48
49
  </div>
</template>

<script>
50
import _ from '@/lodash'
51
52
53
54
55
import axios from 'axios'
import PlayButton from '@/components/audio/PlayButton'

export default {
  props: {
56
57
58
    filters: {type: Object, required: true},
    controls: {type: Boolean, default: true},
    showCount: {type: Boolean, default: false},
59
    limit: {type: Number, default: 12},
60
61
62
63
64
65
66
  },
  components: {
    PlayButton
  },
  data () {
    return {
      albums: [],
67
      count: 0,
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
      isLoading: false,
      errors: null,
      previousPage: null,
      nextPage: null
    }
  },
  created () {
    this.fetchData('albums/')
  },
  methods: {
    fetchData (url) {
      if (!url) {
        return
      }
      this.isLoading = true
      let self = this
      let params = _.clone(this.filters)
      params.page_size = this.limit
      params.offset = this.offset
      axios.get(url, {params: params}).then((response) => {
        self.previousPage = response.data.previous
        self.nextPage = response.data.next
        self.isLoading = false
        self.albums = response.data.results
92
        self.count = response.data.count
93
94
95
96
97
98
99
100
101
102
103
104
      }, error => {
        self.isLoading = false
        self.errors = error.backendErrors
      })
    },
    updateOffset (increment) {
      if (increment) {
        this.offset += this.limit
      } else {
        this.offset = Math.max(this.offset - this.limit, 0)
      }
    },
Eliot Berriot's avatar
Eliot Berriot committed
105
    getImageUrl (album) {
106
107
      let url = '../../../assets/audio/default-cover.png'

108
109
      if (album.cover.original) {
        url = this.$store.getters['instance/absoluteUrl'](album.cover.medium_square_crop)
110
      } else {
Eliot Berriot's avatar
Eliot Berriot committed
111
        return null
112
      }
Eliot Berriot's avatar
Eliot Berriot committed
113
      return url
114
115
116
117
118
    }
  },
  watch: {
    offset () {
      this.fetchData()
119
120
121
    },
    "$store.state.moderation.lastUpdate": function () {
      this.fetchData('albums/')
122
123
124
125
126
    }
  }
}
</script>
<style scoped lang="scss">
Eliot Berriot's avatar
Eliot Berriot committed
127
@import "../../../style/vendor/media";
128
129

.default-cover {
Eliot Berriot's avatar
Eliot Berriot committed
130
  background-image: url("../../../assets/audio/default-cover.png") !important;
131
132
}

133
134
135
.wrapper {
  width: 100%;
}
136
.ui.cards {
137
  justify-content: flex-start;
138
}
139
.ui.five.cards > .card {
140
141
142
143
144
145
146
147
148
149
150
151
  width: 15em;
}
.with-overlay {
  background-size: cover !important;
  background-position: center !important;
  height: 15em;
  width: 15em;
  display: flex !important;
  justify-content: center !important;
  align-items: center !important;
}
</style>
152
153
154
155
156
<style>
.ui.cards .ui.button {
  margin-right: 0px;
}
</style>