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