radiocampus: style update
This commit is contained in:
153
radiocampus/assets/src/components/ARows.vue
Normal file
153
radiocampus/assets/src/components/ARows.vue
Normal file
@ -0,0 +1,153 @@
|
||||
<template>
|
||||
<table class="table is-stripped is-fullwidth">
|
||||
<thead>
|
||||
<a-row :context="context" :columns="columnNames"
|
||||
:orderable="columnsOrderable" cellTag="th"
|
||||
@move="moveColumn">
|
||||
<template v-if="$slots['header-head']" v-slot:head="data">
|
||||
<slot name="header-head" v-bind="data"/>
|
||||
</template>
|
||||
<template v-if="$slots['header-tail']" v-slot:tail="data">
|
||||
<slot name="header-tail" v-bind="data"/>
|
||||
</template>
|
||||
<template v-for="column of columns" v-bind:key="column.name"
|
||||
v-slot:[column.name]="data">
|
||||
<slot :name="'header-' + column.name" v-bind="data">
|
||||
{{ column.label }}
|
||||
<span v-if="column.help" class="icon small"
|
||||
:title="column.help">
|
||||
<i class="fa fa-circle-question"/>
|
||||
</span>
|
||||
</slot>
|
||||
</template>
|
||||
</a-row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<slot name="head"/>
|
||||
<template v-for="(item,row) in items" :key="row">
|
||||
<!-- data-index comes from AList component drag & drop -->
|
||||
<a-row :context="context" :item="item" :cell="{row}" :columns="columnNames" :data-index="row"
|
||||
:data-row="row"
|
||||
:draggable="orderable"
|
||||
@dragstart="onDragStart" @dragover="onDragOver" @drop="onDrop"
|
||||
@cell="onCellEvent(row, $event)">
|
||||
<template v-for="[name,slot] of rowSlots" :key="slot" v-slot:[slot]="data">
|
||||
<slot :name="name" v-bind="data"/>
|
||||
</template>
|
||||
</a-row>
|
||||
</template>
|
||||
<slot name="tail"/>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
<script>
|
||||
import AList from './AList.vue'
|
||||
import ARow from './ARow.vue'
|
||||
|
||||
const Component = {
|
||||
extends: AList,
|
||||
components: { ARow },
|
||||
//! Event:
|
||||
//! - cell(event): an event occured inside cell
|
||||
//! - colmove({from,to}), colmove(): columns moved
|
||||
emits: ['cell', 'colmove'],
|
||||
|
||||
props: {
|
||||
...AList.props,
|
||||
//! Context object
|
||||
context: {type: Object, default: () => ({})},
|
||||
|
||||
//! Ordered list of columns, as objects with:
|
||||
//! - name: item attribute value
|
||||
//! - label: display label
|
||||
//! - help: help text
|
||||
//! - hidden: if true, field is hidden
|
||||
columns: Array,
|
||||
//! If True, columns are orderable
|
||||
columnsOrderable: Boolean,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
...super.data,
|
||||
// TODO: add observer
|
||||
columns_: [...this.columns],
|
||||
extraItem: new this.set.model(),
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
columnNames() { return this.columns_.map(c => c.name) },
|
||||
columnLabels() { return this.columns_.reduce(
|
||||
(labels, c) => ({...labels, [c.name]: c.label}),
|
||||
{}
|
||||
)},
|
||||
rowSlots() {
|
||||
return Object.keys(this.$slots).filter(x => x.startsWith('row-'))
|
||||
.map(x => [x, x.slice(4)])
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
// TODO: use in tracklist
|
||||
sortColumns(names) {
|
||||
const ordered = names.map(n => this.columns_.find(c => c.name == n)).filter(c => !!c);
|
||||
const remaining = this.columns_.filter(c => names.indexOf(c.name) == -1)
|
||||
this.columns_ = [...ordered, ...remaining]
|
||||
this.$emit('colmove')
|
||||
},
|
||||
|
||||
/**
|
||||
* Move column using provided event object (as `{from, to}`)
|
||||
*/
|
||||
moveColumn(event) {
|
||||
const {from, to} = event
|
||||
const value = this.columns_[from]
|
||||
this.columns_.splice(from, 1)
|
||||
this.columns_.splice(to, 0, value)
|
||||
this.$emit('colmove', event)
|
||||
},
|
||||
|
||||
/**
|
||||
* React on 'cell' event, re-emitting it with additional values:
|
||||
* - `set`: data set
|
||||
* - `row`: row index
|
||||
*
|
||||
* @param {Number} row: row index
|
||||
* @param {} data: cell's event data
|
||||
*/
|
||||
onCellEvent(row, event) {
|
||||
if(event.name == 'focus')
|
||||
this.focus(event.data, event.cell)
|
||||
this.$emit('cell', {
|
||||
...event, row,
|
||||
set: this.set
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Return row component at provided index
|
||||
*/
|
||||
getRow(row) {
|
||||
const els = this.$el.querySelectorAll('tr')
|
||||
for(var el of els)
|
||||
if(el.__row && row == Number(el.dataset.row))
|
||||
return el.__row
|
||||
},
|
||||
|
||||
/**
|
||||
* Focus on a cell
|
||||
*/
|
||||
focus(row, col, from=null) {
|
||||
if(from)
|
||||
row += from.row
|
||||
row = this.getRow(row)
|
||||
row && row.focus(col, from)
|
||||
},
|
||||
},
|
||||
}
|
||||
Component.props.itemTag.default = 'tr'
|
||||
Component.props.listTag.default = 'tbody'
|
||||
|
||||
export default Component
|
||||
</script>
|
||||
Reference in New Issue
Block a user