work on playlist & tracklist
This commit is contained in:
@ -3,7 +3,6 @@ import './index.js'
|
||||
|
||||
import App from './app';
|
||||
import {admin as components} from './components'
|
||||
import Track from './track'
|
||||
|
||||
const AdminApp = {
|
||||
...App,
|
||||
@ -12,7 +11,6 @@ const AdminApp = {
|
||||
data() {
|
||||
return {
|
||||
...super.data,
|
||||
Track,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,12 +6,17 @@
|
||||
<div class="modal-card-title">
|
||||
<slot name="title">{{ title }}</slot>
|
||||
</div>
|
||||
<button type="button" class="delete square" aria-label="close" @click="close">
|
||||
<span class="icon">
|
||||
<i class="fa fa-close"></i>
|
||||
</span>
|
||||
</button>
|
||||
</header>
|
||||
<section class="modal-card-body">
|
||||
<slot name="default"></slot>
|
||||
<slot name="default" :item="item"></slot>
|
||||
</section>
|
||||
<div class="modal-card-foot align-right">
|
||||
<slot name="footer" :close="close"></slot>
|
||||
<slot name="footer" :item="item" :close="close"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@ -24,13 +29,24 @@ export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
///! If true, modal is open
|
||||
active: false,
|
||||
///! Item or data passed down to slots.
|
||||
item: null,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
open() { this.active = true; },
|
||||
close() { this.active = false; },
|
||||
///! Open modal dialog. Set provided `item` to dialog's one.
|
||||
open(item=null) {
|
||||
this.active = true
|
||||
this.item = item
|
||||
},
|
||||
///! Close modal and reset item to null.
|
||||
close() {
|
||||
this.active = false
|
||||
this.item = null
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -37,10 +37,6 @@
|
||||
<span class="fas fa-pause" v-if="playing"></span>
|
||||
<span class="fas fa-play" v-else></span>
|
||||
</button>
|
||||
<!--
|
||||
<div class="media-cover" v-if="current && current.data.cover">
|
||||
<img :src="current.data.cover" class="cover" />
|
||||
</div> -->
|
||||
<div :class="['a-player-bar-content', loaded && duration ? 'has-progress' : '']">
|
||||
<slot name="content" :loaded="loaded" :live="live" :current="current"></slot>
|
||||
</div>
|
||||
|
105
assets/src/components/APlaylistEditor.vue
Normal file
105
assets/src/components/APlaylistEditor.vue
Normal file
@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<div class="a-playlist-editor">
|
||||
<a-rows :set="set" :columns="columns"
|
||||
:labels="initData.fields" :allow-create="true" :orderable="true"
|
||||
@move="listItemMove">
|
||||
<template v-for="[name,slot] of rowsSlots" :key="slot"
|
||||
v-slot:[slot]="data">
|
||||
<slot v-if="name != 'row-tail'" :name="name" v-bind="data"/>
|
||||
</template>
|
||||
</a-rows>
|
||||
|
||||
<div class="flex-row">
|
||||
<div class="flex-grow-1 flex-row">
|
||||
</div>
|
||||
<div class="flex-grow-1 align-right">
|
||||
<button type="button" class="button square is-warning p-2"
|
||||
@click="loadData({items: this.initData.items},true)"
|
||||
:title="labels.discard_changes"
|
||||
:aria-label="labels.discard_changes"
|
||||
>
|
||||
<span class="icon"><i class="fa fa-rotate" /></span>
|
||||
</button>
|
||||
<button type="button" class="button square is-primary p-2"
|
||||
@click="this.set.push(new this.set.model())"
|
||||
:title="labels.add_sound"
|
||||
:aria-label="labels.add_sound"
|
||||
>
|
||||
<span class="icon"><i class="fa fa-plus"/></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
// import {dropRightWhile, cloneDeep, isEqual} from 'lodash'
|
||||
import {cloneDeep} from 'lodash'
|
||||
import Model, {Set} from '../model'
|
||||
|
||||
// import AActionButton from './AActionButton'
|
||||
import ARows from './ARows'
|
||||
// import AModal from "./AModal"
|
||||
|
||||
export default {
|
||||
components: {ARows},
|
||||
|
||||
props: {
|
||||
initData: Object,
|
||||
dataPrefix: String,
|
||||
labels: Object,
|
||||
settingsUrl: String,
|
||||
columns: {
|
||||
type: Array,
|
||||
default: () => ['name', "type", 'is_public', 'is_downloadable']
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
set: new Set(Model),
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
items() {
|
||||
return this.set.items
|
||||
},
|
||||
|
||||
rowsSlots() {
|
||||
return Object.keys(this.$slots)
|
||||
.filter(x => x.startsWith('row-') || x.startsWith('rows-'))
|
||||
.map(x => [x, x.startsWith('rows-') ? x.slice(5) : x])
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
listItemMove({from, to, set}) {
|
||||
set.move(from, to);
|
||||
},
|
||||
|
||||
/**
|
||||
* Load initial data
|
||||
*/
|
||||
loadData({items=[] /*, settings=null*/}, reset=false) {
|
||||
if(reset) {
|
||||
this.set.items = []
|
||||
}
|
||||
for(var index in items)
|
||||
this.set.push(cloneDeep(items[index]))
|
||||
// if(settings)
|
||||
// this.settingsSaved(settings)
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
watch: {
|
||||
initData(val) {
|
||||
this.loadData(val)
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.initData && this.loadData(this.initData)
|
||||
},
|
||||
}
|
||||
</script>
|
@ -3,7 +3,7 @@
|
||||
<div ref="list" :class="['a-select-file-list', listClass]">
|
||||
<!-- upload -->
|
||||
<form ref="uploadForm" class="flex-column" v-if="state == STATE.DEFAULT">
|
||||
<div class="field flex-grow-1" v-if="!uploadFile">
|
||||
<div class="field flex-grow-1">
|
||||
<label class="label">{{ uploadLabel }}</label>
|
||||
<input type="file" ref="uploadFile" :name="uploadFieldName" @change="onSubmit"/>
|
||||
</div>
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
</section>
|
||||
<section v-show="page == Page.List" class="panel">
|
||||
<a-rows :set="set" :columns="columns" :labels="labels"
|
||||
<a-rows :set="set" :columns="columns" :labels="initData.fields"
|
||||
:allow-create="true"
|
||||
:orderable="true" @move="listItemMove" @colmove="columnMove"
|
||||
@cell="onCellEvent">
|
||||
@ -49,8 +49,8 @@
|
||||
<td class="align-right pr-0">
|
||||
<button type="button" class="button square"
|
||||
@click.stop="items.splice(data.row,1)"
|
||||
:title="labels.remove_track"
|
||||
:aria-label="labels.remove_track">
|
||||
:title="labels.remove_item"
|
||||
:aria-label="labels.remove_item">
|
||||
<span class="icon"><i class="fa fa-trash" /></span>
|
||||
</button>
|
||||
</td>
|
||||
@ -82,8 +82,8 @@
|
||||
</button>
|
||||
<button type="button" class="button square is-primary p-2" v-if="page == Page.List"
|
||||
@click="this.set.push(new this.set.model())"
|
||||
:title="labels.add_track"
|
||||
:aria-label="labels.add_track"
|
||||
:title="labels.add_item"
|
||||
:aria-label="labels.add_item"
|
||||
>
|
||||
<span class="icon"><i class="fa fa-plus"/></span>
|
||||
</button>
|
||||
@ -99,7 +99,7 @@
|
||||
<table class="table is-bordered"
|
||||
style="vertical-align: middle">
|
||||
<tr>
|
||||
<a-row :columns="columns" :item="labels"
|
||||
<a-row :columns="columns" :item="initData.fields"
|
||||
@move="formatMove" :orderable="true">
|
||||
<template v-slot:cell-after="{cell}">
|
||||
<td style="cursor:pointer;" v-if="cell.col < columns.length-1">
|
||||
@ -149,8 +149,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import {dropRightWhile, cloneDeep, isEqual} from 'lodash'
|
||||
import {Set} from '../model'
|
||||
import Track from '../track'
|
||||
import Model, {Set} from '../model'
|
||||
|
||||
import AActionButton from './AActionButton'
|
||||
import ARow from './ARow'
|
||||
@ -165,6 +164,7 @@ export const Page = {
|
||||
export default {
|
||||
components: { AActionButton, ARow, ARows, AModal },
|
||||
props: {
|
||||
///! initial data as: {items: [], fields: {column_name: label, settings: {}}
|
||||
initData: Object,
|
||||
dataPrefix: String,
|
||||
labels: Object,
|
||||
@ -182,7 +182,7 @@ export default {
|
||||
return {
|
||||
Page: Page,
|
||||
page: Page.Text,
|
||||
set: new Set(Track),
|
||||
set: new Set(Model),
|
||||
extraData: {},
|
||||
settings,
|
||||
savedSettings: cloneDeep(settings),
|
||||
|
@ -7,15 +7,16 @@ import AList from './AList'
|
||||
import APage from './APage'
|
||||
import APlayer from './APlayer'
|
||||
import APlaylist from './APlaylist'
|
||||
import ATracklistEditor from './ATracklistEditor'
|
||||
import AProgress from './AProgress'
|
||||
import ASoundItem from './ASoundItem'
|
||||
import ASwitch from './ASwitch'
|
||||
import AStatistics from './AStatistics'
|
||||
import AStreamer from './AStreamer'
|
||||
|
||||
import AModal from "./AModal"
|
||||
import ASelectFile from "./ASelectFile"
|
||||
import AStatistics from './AStatistics'
|
||||
import AStreamer from './AStreamer'
|
||||
import ATracklistEditor from './ATracklistEditor'
|
||||
import APlaylistEditor from './APlaylistEditor'
|
||||
|
||||
/**
|
||||
* Core components
|
||||
@ -35,5 +36,5 @@ export const admin = {
|
||||
|
||||
export const dashboard = {
|
||||
...base,
|
||||
AActionButton, ASelectFile, AModal, ATracklistEditor,
|
||||
AActionButton, ASelectFile, AModal, ATracklistEditor, APlaylistEditor
|
||||
}
|
||||
|
@ -8,13 +8,11 @@ const DashboardApp = {
|
||||
...App,
|
||||
components: {...App.components, ...components},
|
||||
|
||||
/*
|
||||
data() {
|
||||
return {
|
||||
editPageContent: null,
|
||||
modalItem: null,
|
||||
}
|
||||
},
|
||||
*/
|
||||
|
||||
methods: {
|
||||
...App.methods,
|
||||
|
@ -1,5 +0,0 @@
|
||||
import Model from './model'
|
||||
|
||||
export default class Track extends Model {
|
||||
static getId(data) { return data.pk }
|
||||
}
|
Reference in New Issue
Block a user