rename playlist-editor to tracklist-editor; refactor player
This commit is contained in:
		@ -44,7 +44,7 @@ class EpisodeForm(PageForm):
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = models.Episode
 | 
			
		||||
        fields = ["content"]
 | 
			
		||||
        fields = PageForm.Meta.fields
 | 
			
		||||
 | 
			
		||||
    def save(self, commit=True):
 | 
			
		||||
        file_obj = self.cleaned_data["new_podcast"]
 | 
			
		||||
 | 
			
		||||
@ -32,10 +32,23 @@ class Episode(Page):
 | 
			
		||||
    @cached_property
 | 
			
		||||
    def podcasts(self):
 | 
			
		||||
        """Return serialized data about podcasts."""
 | 
			
		||||
        from .sound import Sound
 | 
			
		||||
        from ..serializers import PodcastSerializer
 | 
			
		||||
 | 
			
		||||
        podcasts = [PodcastSerializer(s).data for s in self.sound_set.public().order_by("type")]
 | 
			
		||||
        query = self.sound_set.public().order_by("type")
 | 
			
		||||
        return self._to_podcasts(query, PodcastSerializer)
 | 
			
		||||
 | 
			
		||||
    @cached_property
 | 
			
		||||
    def sounds(self):
 | 
			
		||||
        """Return serialized data about all related sounds."""
 | 
			
		||||
        from ..serializers import SoundSerializer
 | 
			
		||||
 | 
			
		||||
        query = self.sound_set.order_by("type")
 | 
			
		||||
        return self._to_podcasts(query, SoundSerializer)
 | 
			
		||||
 | 
			
		||||
    def _to_podcasts(self, items, serializer_class):
 | 
			
		||||
        from .sound import Sound
 | 
			
		||||
 | 
			
		||||
        podcasts = [serializer_class(s).data for s in items]
 | 
			
		||||
        if self.cover:
 | 
			
		||||
            options = {"size": (128, 128), "crop": "scale"}
 | 
			
		||||
            cover = get_thumbnailer(self.cover).get_thumbnail(options).url
 | 
			
		||||
 | 
			
		||||
@ -14,5 +14,5 @@ class UserSettings(models.Model):
 | 
			
		||||
        verbose_name=_("User"),
 | 
			
		||||
        related_name="aircox_settings",
 | 
			
		||||
    )
 | 
			
		||||
    playlist_editor_columns = models.JSONField(_("Playlist Editor Columns"))
 | 
			
		||||
    playlist_editor_sep = models.CharField(_("Playlist Editor Separator"), max_length=16)
 | 
			
		||||
    tracklist_editor_columns = models.JSONField(_("Playlist Editor Columns"))
 | 
			
		||||
    tracklist_editor_sep = models.CharField(_("Playlist Editor Separator"), max_length=16)
 | 
			
		||||
 | 
			
		||||
@ -35,10 +35,10 @@ class TrackSerializer(TaggitSerializer, serializers.ModelSerializer):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserSettingsSerializer(serializers.ModelSerializer):
 | 
			
		||||
    # TODO: validate fields values (playlist_editor_columns at least)
 | 
			
		||||
    # TODO: validate fields values (tracklist_editor_columns at least)
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = UserSettings
 | 
			
		||||
        fields = ("playlist_editor_columns", "playlist_editor_sep")
 | 
			
		||||
        fields = ("tracklist_editor_columns", "tracklist_editor_sep")
 | 
			
		||||
 | 
			
		||||
    def create(self, validated_data):
 | 
			
		||||
        user = self.context.get("user")
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ __all__ = ("SoundSerializer", "PodcastSerializer")
 | 
			
		||||
 | 
			
		||||
class SoundSerializer(serializers.ModelSerializer):
 | 
			
		||||
    file = serializers.FileField(use_url=False)
 | 
			
		||||
    type_display = serializers.SerializerMethodField()
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Sound
 | 
			
		||||
@ -16,14 +17,19 @@ class SoundSerializer(serializers.ModelSerializer):
 | 
			
		||||
            "program",
 | 
			
		||||
            "episode",
 | 
			
		||||
            "type",
 | 
			
		||||
            "type_display",
 | 
			
		||||
            "file",
 | 
			
		||||
            "duration",
 | 
			
		||||
            "mtime",
 | 
			
		||||
            "is_good_quality",
 | 
			
		||||
            "is_public",
 | 
			
		||||
            "is_downloadable",
 | 
			
		||||
            "url",
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
    def get_type_display(self, obj):
 | 
			
		||||
        return obj.get_type_display()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PodcastSerializer(serializers.ModelSerializer):
 | 
			
		||||
    # serializers.HyperlinkedIdentityField(view_name='sound', format='html')
 | 
			
		||||
 | 
			
		||||
@ -533,7 +533,7 @@
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.a-playlist-editor .dropdown {
 | 
			
		||||
.a-tracklist-editor .dropdown {
 | 
			
		||||
  display: unset !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -533,7 +533,7 @@
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.a-playlist-editor .dropdown {
 | 
			
		||||
.a-tracklist-editor .dropdown {
 | 
			
		||||
  display: unset !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -7,7 +7,7 @@
 | 
			
		||||
<div id="inline-tracks" class="box mb-5">
 | 
			
		||||
    {{ admin_formset.non_form_errors }}
 | 
			
		||||
 | 
			
		||||
    <a-playlist-editor
 | 
			
		||||
    <a-tracklist-editor
 | 
			
		||||
            :labels="{% track_inline_labels %}"
 | 
			
		||||
            :init-data="{% track_inline_data formset=formset %}"
 | 
			
		||||
            settings-url="{% url "api:user-settings" %}"
 | 
			
		||||
@ -79,7 +79,7 @@
 | 
			
		||||
        </template>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
        {% endfor %}
 | 
			
		||||
    </a-playlist-editor>
 | 
			
		||||
    </a-tracklist-editor>
 | 
			
		||||
</div>
 | 
			
		||||
{% endwith %}
 | 
			
		||||
{% endwith %}
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,42 @@
 | 
			
		||||
{% load static i18n humanize honeypot aircox %}
 | 
			
		||||
 | 
			
		||||
{% block page_form %}
 | 
			
		||||
<a-episode :page="{title: "{{ object.title }}", podcasts: {{ object.sounds|json }}}">
 | 
			
		||||
    <template v-slot="{podcasts,page}">
 | 
			
		||||
        {{ block.super }}
 | 
			
		||||
        <hr/>
 | 
			
		||||
{% include "./widgets/playlist_editor.html" with formset=playlist_formset %}
 | 
			
		||||
        {% include "./widgets/tracklist_editor.html" with formset=playlist_formset %}
 | 
			
		||||
        <hr/>
 | 
			
		||||
        <section class="container">
 | 
			
		||||
            <h3 class="title">{% translate "Sound files" %}</h3>
 | 
			
		||||
            <a-playlist v-if="page" :set="podcasts"
 | 
			
		||||
                    name="{{ page.title }}"
 | 
			
		||||
                    list-class="menu-list" item-class="menu-item"
 | 
			
		||||
                    :player="player" :actions="['play']"
 | 
			
		||||
                    @select="player.playItems('queue', $event.item)">
 | 
			
		||||
                <template #after-title="{item}">
 | 
			
		||||
                    <span class="flex-grow-1">
 | 
			
		||||
                        [[ item.data.type_display ]]
 | 
			
		||||
                        <span v-if="item.data.is_public">
 | 
			
		||||
                            /
 | 
			
		||||
                            {% translate "public" %}
 | 
			
		||||
                        </span>
 | 
			
		||||
                        <span v-if="item.data.is_downloadable">
 | 
			
		||||
                            /
 | 
			
		||||
                            {% translate "downloadable" %}
 | 
			
		||||
                        </span>
 | 
			
		||||
                    </span>
 | 
			
		||||
                </template>
 | 
			
		||||
                <template #actions="{item}">
 | 
			
		||||
                    <button type="button" class="button"
 | 
			
		||||
                            title="{% translate "Edit" %}">
 | 
			
		||||
                        <span class="icon">
 | 
			
		||||
                            <i class="fa fa-edit"></i>
 | 
			
		||||
                        </span>
 | 
			
		||||
                    </button>
 | 
			
		||||
                </template>
 | 
			
		||||
            </a-playlist>
 | 
			
		||||
        </section>
 | 
			
		||||
    </template>
 | 
			
		||||
</a-episode>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
@ -39,7 +39,7 @@
 | 
			
		||||
                            icon="fa fa-trash"
 | 
			
		||||
                            confirm="{% translate "Are you sure you want to remove this item from server?" %}"
 | 
			
		||||
                            method="DELETE"
 | 
			
		||||
                            :url="'{% url "api:image-detail" pk="123" %}'.replace('123', item.id)"q
 | 
			
		||||
                            :url="'{% url "api:image-detail" pk="123" %}'.replace('123', item.id)"
 | 
			
		||||
                            @done="load(lastUrl)">
 | 
			
		||||
                        </a-action-button>
 | 
			
		||||
                    </div>
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,7 @@ The audio player
 | 
			
		||||
 | 
			
		||||
    <a-player ref="player"
 | 
			
		||||
            :live-args="{% player_live_attr %}"
 | 
			
		||||
            :playlists="{pin: ['{% translate "Bookmarks" %}', 'fa fa-star'], queue: ['{% translate 'Playlist' %}', 'fa fa-list']}"
 | 
			
		||||
            button-title="{% translate "Play or pause audio" %}">
 | 
			
		||||
        <template v-slot:content="{ loaded, live, current }">
 | 
			
		||||
            <h4 v-if="loaded" class="title">
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ Context:
 | 
			
		||||
    {{ formset.non_form_errors }}
 | 
			
		||||
    <!-- formset.management_form -->
 | 
			
		||||
 | 
			
		||||
    <a-playlist-editor
 | 
			
		||||
    <a-tracklist-editor
 | 
			
		||||
            :labels="{% track_inline_labels %}"
 | 
			
		||||
            :init-data="{% track_inline_data formset=formset %}"
 | 
			
		||||
            :default-columns="[{% for f in fields %}{% if f != "position" %}'{{ f }}',{% endif %}{% endfor %}]"
 | 
			
		||||
@ -74,6 +74,6 @@ Context:
 | 
			
		||||
        </template>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
        {% endfor %}
 | 
			
		||||
    </a-playlist-editor>
 | 
			
		||||
    </a-tracklist-editor>
 | 
			
		||||
</div>
 | 
			
		||||
{% endwith %}
 | 
			
		||||
@ -52,7 +52,13 @@ class EpisodeUpdateView(UserPassesTestMixin, BaseProgramMixin, PageUpdateView):
 | 
			
		||||
    form_class = EpisodeForm
 | 
			
		||||
    template_name = "aircox/episode_form.html"
 | 
			
		||||
 | 
			
		||||
    playlist_fields = ("position", "artist", "title", "tags", "album", "info")
 | 
			
		||||
    playlist_fields = (
 | 
			
		||||
        "position",
 | 
			
		||||
        "artist",
 | 
			
		||||
        "title",
 | 
			
		||||
        "tags",
 | 
			
		||||
        "album",
 | 
			
		||||
    )
 | 
			
		||||
    """Playlist editor's ordered fields."""
 | 
			
		||||
 | 
			
		||||
    def test_func(self):
 | 
			
		||||
 | 
			
		||||
@ -1,15 +1,20 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="a-player">
 | 
			
		||||
        <div :class="['a-player-panels', panel ? 'is-open' : '']">
 | 
			
		||||
            <APlaylist ref="pin" class="a-player-panel a-playlist" v-show="panel == 'pin' && sets.pin.length"
 | 
			
		||||
                name="Pinned"
 | 
			
		||||
                :actions="['page']"
 | 
			
		||||
                :editable="true" :player="self" :set="sets.pin" @select="togglePlay('pin', $event.index)"
 | 
			
		||||
            <template v-for="(info, key) in playlists" v-bind:key="key">
 | 
			
		||||
                <APlaylist
 | 
			
		||||
                        :ref="key" class="a-player-panel a-playlist"
 | 
			
		||||
                        v-show="panel == key && sets[key].length"
 | 
			
		||||
                        :actions="['page', key != 'pin' && 'pin' || '']"
 | 
			
		||||
                        :editable="true" :player="self" :set="sets[key]"
 | 
			
		||||
                        @select="togglePlay(key, $event.index)"
 | 
			
		||||
                        listClass="menu-list" itemClass="menu-item">
 | 
			
		||||
                    <template v-slot:header="">
 | 
			
		||||
                        <div class="title is-flex-grow-1">
 | 
			
		||||
                        <span class="icon"><span class="fa fa-star"></span></span>
 | 
			
		||||
                        Pinned
 | 
			
		||||
                            <span class="icon">
 | 
			
		||||
                                <i :class="info[1]"></i>
 | 
			
		||||
                            </span>
 | 
			
		||||
                            {{ info[0] }}
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <button class="action button no-border">
 | 
			
		||||
                            <span class="icon" @click.stop="togglePanel()">
 | 
			
		||||
@ -18,22 +23,7 @@
 | 
			
		||||
                        </button>
 | 
			
		||||
                    </template>
 | 
			
		||||
                </APlaylist>
 | 
			
		||||
            <APlaylist ref="queue" class="a-player-panel a-playlist" v-show="panel == 'queue' && sets.queue.length"
 | 
			
		||||
                :actions="['page']"
 | 
			
		||||
                :editable="true" :player="self" :set="sets.queue" @select="togglePlay('queue', $event.index)"
 | 
			
		||||
                listClass="menu-list" itemClass="menu-item">
 | 
			
		||||
                <template v-slot:header="">
 | 
			
		||||
                    <div class="title is-flex-grow-1">
 | 
			
		||||
                        <span class="icon"><span class="fa fa-list"></span></span>
 | 
			
		||||
                        Playlist
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <button class="action button no-border">
 | 
			
		||||
                        <span class="icon" @click.stop="togglePanel()">
 | 
			
		||||
                            <i class="fa fa-close"></i>
 | 
			
		||||
                        </span>
 | 
			
		||||
                    </button>
 | 
			
		||||
            </template>
 | 
			
		||||
            </APlaylist>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="a-player-progress" v-if="loaded && duration">
 | 
			
		||||
@ -59,18 +49,18 @@
 | 
			
		||||
                    <span class="fa fa-circle"></span>
 | 
			
		||||
                </span>
 | 
			
		||||
            </button>
 | 
			
		||||
            <button ref="pinPlaylistButton" :class="playlistButtonClass('pin')"
 | 
			
		||||
                    @click="togglePanel('pin')" v-show="sets.pin.length">
 | 
			
		||||
                <span class="is-size-6" v-if="sets.pin.length">
 | 
			
		||||
                    {{ sets.pin.length }}</span>
 | 
			
		||||
                <span class="icon"><span class="fa fa-star"></span></span>
 | 
			
		||||
            </button>
 | 
			
		||||
            <button :class="playlistButtonClass('queue')"
 | 
			
		||||
                    @click="togglePanel('queue')" v-show="sets.queue.length">
 | 
			
		||||
                <span class="is-size-6" v-if="sets.queue.length">
 | 
			
		||||
                    {{ sets.queue.length }}</span>
 | 
			
		||||
                <span class="icon"><span class="fa fa-list"></span></span>
 | 
			
		||||
            <template v-if="sets">
 | 
			
		||||
                <template v-for="(info, key) in playlists" v-bind:key="key">
 | 
			
		||||
                    <button :class="playlistButtonClass(key)"
 | 
			
		||||
                            @click="togglePanel(key)"
 | 
			
		||||
                            v-show="sets[key] && sets[key].length">
 | 
			
		||||
                        <span class="is-size-6">{{ sets[key] && sets[key].length }}</span>
 | 
			
		||||
                        <span class="icon">
 | 
			
		||||
                            <i :class="info[1]"></i>
 | 
			
		||||
                        </span>
 | 
			
		||||
                    </button>
 | 
			
		||||
                </template>
 | 
			
		||||
            </template>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
@ -108,6 +98,11 @@ export default {
 | 
			
		||||
        let live = this.liveArgs ? reactive(new Live(this.liveArgs)) : null;
 | 
			
		||||
        live && live.refresh();
 | 
			
		||||
 | 
			
		||||
        const sets = {}
 | 
			
		||||
        for(const key in this.playlists)
 | 
			
		||||
            sets[key] = Set.storeLoad(Sound, 'playlist.' + key,
 | 
			
		||||
                {max: 30, unique: true})
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
            audio, duration: 0, currentTime: 0, state: State.paused,
 | 
			
		||||
            live,
 | 
			
		||||
@ -119,16 +114,15 @@ export default {
 | 
			
		||||
            //! current playing playlist name
 | 
			
		||||
            playlistName: null,
 | 
			
		||||
            //! players' playlists' sets
 | 
			
		||||
            sets: {
 | 
			
		||||
                queue: Set.storeLoad(Sound, "playlist.queue", { max: 30, unique: true }),
 | 
			
		||||
                pin: Set.storeLoad(Sound, "player.pin", { max: 30, unique: true }),
 | 
			
		||||
            }
 | 
			
		||||
            sets,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    props: {
 | 
			
		||||
        buttonTitle: String,
 | 
			
		||||
        liveArgs: Object,
 | 
			
		||||
        ///! dict of {'slug': ['Label', 'icon']}
 | 
			
		||||
        playlists: Object,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    computed: {
 | 
			
		||||
@ -138,7 +132,7 @@ export default {
 | 
			
		||||
        loading() { return this.state == State.loading; },
 | 
			
		||||
 | 
			
		||||
        playlist() {
 | 
			
		||||
            return this.playlistName ? this.$refs[this.playlistName] : null;
 | 
			
		||||
            return this.playlistName ? this.$refs[this.playlistName][0] : null;
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        current() {
 | 
			
		||||
@ -178,8 +172,8 @@ export default {
 | 
			
		||||
        _setPlaylist(playlist) {
 | 
			
		||||
            this.playlistName = playlist;
 | 
			
		||||
            for(var p in this.sets)
 | 
			
		||||
                if(p != playlist)
 | 
			
		||||
                    this.$refs[p].unselect();
 | 
			
		||||
                if(p != playlist && this.$refs[p])
 | 
			
		||||
                    this.$refs[p][0].unselect();
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        /// Load a sound from playlist or live
 | 
			
		||||
@ -188,7 +182,7 @@ export default {
 | 
			
		||||
 | 
			
		||||
            // from playlist
 | 
			
		||||
            if(playlist !== null && index != -1) {
 | 
			
		||||
                let item = this.$refs[playlist].get(index);
 | 
			
		||||
                let item = this.$refs[playlist][0].get(index);
 | 
			
		||||
                if(!item)
 | 
			
		||||
                    throw `No sound at index ${index} for playlist ${playlist}`;
 | 
			
		||||
                this.loaded = item
 | 
			
		||||
@ -232,7 +226,7 @@ export default {
 | 
			
		||||
        /// Push and play items
 | 
			
		||||
        playItems(playlist, ...items) {
 | 
			
		||||
            let index = this.push(playlist, ...items);
 | 
			
		||||
            this.$refs[playlist].selectedIndex = index;
 | 
			
		||||
            this.$refs[playlist][0].selectedIndex = index;
 | 
			
		||||
            this.play(playlist, index);
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
@ -264,13 +258,14 @@ export default {
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        //! Pin/Unpin an item
 | 
			
		||||
        togglePin(item) {
 | 
			
		||||
            let index = this.sets.pin.findIndex(item);
 | 
			
		||||
        togglePlaylist(playlist, item) {
 | 
			
		||||
            const set = this.sets[playlist]
 | 
			
		||||
            let index = set.findIndex(item);
 | 
			
		||||
            if(index > -1)
 | 
			
		||||
                this.sets.pin.remove(index);
 | 
			
		||||
                set.remove(index);
 | 
			
		||||
            else {
 | 
			
		||||
                this.sets.pin.push(item);
 | 
			
		||||
                this.$refs.pinPlaylistButton.focus();
 | 
			
		||||
                set.push(item);
 | 
			
		||||
                // this.$refs.pinPlaylistButton.focus();
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,11 @@
 | 
			
		||||
                    :data="item" :index="index" :set="set" :player="player_"
 | 
			
		||||
                    @togglePlay="togglePlay(index)"
 | 
			
		||||
                    :actions="actions">
 | 
			
		||||
                    <template v-slot:actions="{}">
 | 
			
		||||
                    <template #after-title="bindings">
 | 
			
		||||
                        <slot name="after-title" v-bind="bindings"></slot>
 | 
			
		||||
                    </template>
 | 
			
		||||
                    <template #actions="bindings">
 | 
			
		||||
                        <slot name="actions" v-bind="bindings"></slot>
 | 
			
		||||
                        <button class="button" v-if="editable" @click.stop="remove(index,true)">
 | 
			
		||||
                            <span class="icon is-small"><span class="fa fa-close"></span></span>
 | 
			
		||||
                        </button>
 | 
			
		||||
@ -30,6 +34,7 @@ export default {
 | 
			
		||||
 | 
			
		||||
    props: {
 | 
			
		||||
        actions: Array,
 | 
			
		||||
        // FIXME: remove
 | 
			
		||||
        name: String,
 | 
			
		||||
        player: Object,
 | 
			
		||||
        editable: Boolean,
 | 
			
		||||
 | 
			
		||||
@ -5,6 +5,8 @@
 | 
			
		||||
                {{ name || item.name }}
 | 
			
		||||
            </span>
 | 
			
		||||
        </slot>
 | 
			
		||||
        <slot name="after-title" :player="player" :item="item" :loaded="loaded">
 | 
			
		||||
        </slot>
 | 
			
		||||
        <div class="button-group actions">
 | 
			
		||||
            <a class="button action" v-if="hasAction('page')"
 | 
			
		||||
                    :href="item.data.page_url">
 | 
			
		||||
@ -12,13 +14,15 @@
 | 
			
		||||
                    <i class="fa fa-external-link"></i>
 | 
			
		||||
                </span>
 | 
			
		||||
            </a>
 | 
			
		||||
            <a class="button action" v-if="item.data.is_downloadable"
 | 
			
		||||
            <a class="button action"
 | 
			
		||||
                    v-if="hasAction('download') && item.data.is_downloadable"
 | 
			
		||||
                    :href="item.data.url" target="_blank">
 | 
			
		||||
                <span class="icon is-small">
 | 
			
		||||
                    <span class="fa fa-download"></span>
 | 
			
		||||
                </span>
 | 
			
		||||
            </a>
 | 
			
		||||
            <button :class="['button action', pinned ? 'selected' : 'not-selected']" v-if="player && player.sets.pin != $parent.set" @click.stop="player.togglePin(item)">
 | 
			
		||||
            <button :class="['button action', pinned ? 'selected' : 'not-selected']"
 | 
			
		||||
                    v-if="hasAction('pin') && player && player.sets.pin != $parent.set" @click.stop="player.togglePlaylist('pin', item)">
 | 
			
		||||
                <span class="icon is-small">
 | 
			
		||||
                    <span class="fa fa-star"></span>
 | 
			
		||||
                </span>
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="a-playlist-editor">
 | 
			
		||||
    <div class="a-tracklist-editor">
 | 
			
		||||
        <div class="flex-row">
 | 
			
		||||
            <div class="flex-grow-1">
 | 
			
		||||
                <slot name="title" />
 | 
			
		||||
@ -176,8 +176,8 @@ export default {
 | 
			
		||||
 | 
			
		||||
    data() {
 | 
			
		||||
        const settings = {
 | 
			
		||||
            playlist_editor_columns: this.defaultColumns,
 | 
			
		||||
            playlist_editor_sep: ' -- ',
 | 
			
		||||
            tracklist_editor_columns: this.defaultColumns,
 | 
			
		||||
            tracklist_editor_sep: ' -- ',
 | 
			
		||||
        }
 | 
			
		||||
        return {
 | 
			
		||||
            Page: Page,
 | 
			
		||||
@ -198,11 +198,11 @@ export default {
 | 
			
		||||
 | 
			
		||||
        separator: {
 | 
			
		||||
            set(value) {
 | 
			
		||||
                this.settings.playlist_editor_sep = value
 | 
			
		||||
                this.settings.tracklist_editor_sep = value
 | 
			
		||||
                if(this.page == Page.List)
 | 
			
		||||
                    this.updateInput()
 | 
			
		||||
            },
 | 
			
		||||
            get() { return this.settings.playlist_editor_sep }
 | 
			
		||||
            get() { return this.settings.tracklist_editor_sep }
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        columns: {
 | 
			
		||||
@ -210,10 +210,10 @@ export default {
 | 
			
		||||
                var cols = value.filter(x => x in this.defaultColumns)
 | 
			
		||||
                var left = this.defaultColumns.filter(x => !(x in cols))
 | 
			
		||||
                value = cols.concat(left)
 | 
			
		||||
                this.settings.playlist_editor_columns = value
 | 
			
		||||
                this.settings.tracklist_editor_columns = value
 | 
			
		||||
            },
 | 
			
		||||
            get() {
 | 
			
		||||
                return this.settings.playlist_editor_columns
 | 
			
		||||
                return this.settings.tracklist_editor_columns
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
@ -238,8 +238,8 @@ export default {
 | 
			
		||||
 | 
			
		||||
        formatMove({from, to}) {
 | 
			
		||||
            const value = this.columns[from]
 | 
			
		||||
            this.settings.playlist_editor_columns.splice(from, 1)
 | 
			
		||||
            this.settings.playlist_editor_columns.splice(to, 0, value)
 | 
			
		||||
            this.settings.tracklist_editor_columns.splice(from, 1)
 | 
			
		||||
            this.settings.tracklist_editor_columns.splice(to, 0, value)
 | 
			
		||||
            if(this.page == Page.Text)
 | 
			
		||||
                this.updateList()
 | 
			
		||||
            else
 | 
			
		||||
@ -7,7 +7,7 @@ import AList from './AList'
 | 
			
		||||
import APage from './APage'
 | 
			
		||||
import APlayer from './APlayer'
 | 
			
		||||
import APlaylist from './APlaylist'
 | 
			
		||||
import APlaylistEditor from './APlaylistEditor'
 | 
			
		||||
import ATracklistEditor from './ATracklistEditor'
 | 
			
		||||
import AProgress from './AProgress'
 | 
			
		||||
import ASoundItem from './ASoundItem'
 | 
			
		||||
import ASwitch from './ASwitch'
 | 
			
		||||
@ -30,10 +30,10 @@ export default base
 | 
			
		||||
 | 
			
		||||
export const admin = {
 | 
			
		||||
    ...base,
 | 
			
		||||
    AStatistics, AStreamer, APlaylistEditor
 | 
			
		||||
    AStatistics, AStreamer, ATracklistEditor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const dashboard = {
 | 
			
		||||
    ...base,
 | 
			
		||||
    AActionButton, ASelectFile, AModal, APlaylistEditor,
 | 
			
		||||
    AActionButton, ASelectFile, AModal, ATracklistEditor,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -710,7 +710,7 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// ---- playlist editor
 | 
			
		||||
.a-playlist-editor {
 | 
			
		||||
.a-tracklist-editor {
 | 
			
		||||
    .dropdown {
 | 
			
		||||
        display: unset !important;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user