import {Component} from '../../vues6.js' import {Resource, ResourceActions} from '../Resource.js' import {uuid} from '../util.js' import {ActionService} from '../service/Action.service.js' export const Status = Object.freeze({ loading: 'loading', ready: 'ready', errorUnsupported: 'errorUnsupported', saving: 'saving', }) const template = `
{{ title }}
Loading...

This resource does not support listing.

# {{ col.display }}
# {{ col.display }}
` export class ListingComponent extends Component { static get selector() { return 'cobalt-listing' } static get template() { return template } static get props() { return ['resourcekey'] } constructor() { super() this.status = Status.loading this.title = 'Loading...' this.rows = [] this.columns = [] this.actions = [] this.unregister = [] this.id = uuid() /** @var {Resource} */ this.resource = undefined } vue_on_destroy() { this.unregister.forEach(actionName => { if ( window[actionName] ) { delete window[actionName] } }) } async vue_on_create() { this.resource = await Resource.get(this.resourcekey) this.title = this.resource.plural() if ( !this.resource.supports(ResourceActions.read) ) { this.status = Status.errorUnsupported return } await this.load() } async load(reload = false) { this.columns = [...this.resource.configuration.fields] if ( !reload && this.resource.supports(ResourceActions.create) ) { this.actions.push({ title: 'Add New', color: 'success', icon: 'fa-plus', overall: true, type: 'resource', resource: this.resource.key, action: 'insert', defer: true, }) } if ( !reload && this.resource.supports(ResourceActions.update) ) { this.actions.push({ title: 'Edit', color: 'primary', icon: 'fa-edit', type: 'resource', resource: this.resource.key, action: 'update', defer: true, }) } if ( !reload && this.resource.supports(ResourceActions.delete) ) { this.actions.push({ title: 'Delete', color: 'danger', icon: 'fa-trash-alt', type: 'resource', resource: this.resource.key, action: 'delete', defer: true, }) } this.rows = await this.resource.read() this.rows.forEach((row, idx) => row.idx = idx) const order = [] this.columns.forEach((col, i) => { if ( col.sort ) { order.push([i+1, col.sort]) } }) this.status = Status.ready this.$nextTick(() => { $(`#table-${this.id}`).DataTable({ order, data: this.rows, columns: [ { data: 'idx', render: data => `${data + 1}`, }, ...this.columns.map((col, idx) => { return { data: col.key, render: (data, type) => { if ( type === 'display' ) { if ( col.renderer === 'html' ) { return String(data || '') } else if ( col.renderer === 'bool' ) { return data ? 'Yes' : 'No' } else if ( col.renderer === 'date' && data ) { return (new Date(data)).toDisplay() } else if ( col.renderer === 'time' && data ) { return (new Date(data)).toLocaleTimeString() } else if ( col.renderer === 'datetime' && data ) { return `${(new Date(data)).toDisplay()} ${(new Date(data)).toLocaleTimeString()}` } return String(data || '-').replace(//, '>') } return data } } }), { data: 'idx', render: (data, type, row) => { if ( type === 'display' ) { const html = [] this.actions.forEach((action, idx) => { if ( action.overall ) return const actionName = `action_${uuid().replace(/-/g, '')}` this.unregister.push(actionName) window[actionName] = () => { this.onAction(action, row) } html.push(` `) }) return html.join('') } return data } }, ], }) }) } async onAction(action, row) { await ActionService.get().perform(action, row, async () => { this.status = Status.loading await this.load(true) }) } }