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