4 Комити

Аутор SHA1 Порука Датум
  Bing Sun ffca627f48
make_model: fix typo пре 5 година
  Bing Sun 49f6911143
make_model: support order пре 5 година
  Bing Sun 6410ce1b5a
Table: support simple pagination пре 5 година
  Bing Sun 82133fed3b
make_model: be aware of array with empyt slots пре 5 година
2 измењених фајлова са 71 додато и 110 уклоњено
  1. +54
    -103
      src/components/Table.js
  2. +17
    -7
      src/util/make_model.js

+ 54
- 103
src/components/Table.js Прегледај датотеку

@@ -8,25 +8,67 @@ export default initial_vnode => {
// component state // component state
let model = initial_vnode.attrs.model let model = initial_vnode.attrs.model


// displayed columns
let columns = initial_vnode.attrs.columns let columns = initial_vnode.attrs.columns
if (!columns) { if (!columns) {
if (model.configs().selects) { if (model.configs().selects) {
_columns = model.configs().selects.map(select => ({
columns = model.configs().selects.map(select => ({
label: select.alias || select.label label: select.alias || select.label
})) }))
} }
} }


// pagination
let offset = 0 let offset = 0
let limit = initial_vnode.attrs.pagination && initial_vnode.attrs.pagination.size
console.log(limit)
let limit = initial_vnode.attrs.pagination && initial_vnode.attrs.pagination.size || Infinity
let pages = [] // [{activie: boolean, show: boolean}]

function generate_pages() {
if (limit > 0 && limit < Infinity && model.cache().count) {
let active_page = offset / limit

pages = Array.from(Array(Math.floor(model.cache().count / limit) + 1))
.map((_,i) => active_page == i ? {active: true} : {active: false})

if (pages.length <= 10) {
pages.forEach((_, i, pages) => pages[i].show = true)
} else {
// some wicked calculation
let _showed_pages = new Set([0, active_page, pages.length -1])
let l = active_page, r = active_page
while (_showed_pages.size < 10) {
l -= 1
if (l < 0) {
_showed_pages.add(r+1)
r += 1
} else {
_showed_pages.add(l)
}
if (_showed_pages.size < 10) {
r += 1
if (r >= pages.length) {
_showed_pages.add(l-1)
l -= 1
} else {
_showed_pages.add(r)
}
}
}
_showed_pages.forEach(v => pages[v].show = true)
}
}
}

return { return {
view: vnode => { view: vnode => {
// try to generate columns if it is still undefined
// try to generate columns if it is still uninitialized
if (typeof columns == 'undefined' || columns.length == 0) { if (typeof columns == 'undefined' || columns.length == 0) {
columns = model.data() && model.data().length && Object.keys(model.data()[0]).map(key => ({label: key})) || []
columns = model.data(offset, limit) && model.data(offset, limit).length && Object.keys(model.data(offset, limit)[0]).map(key => ({label: key})) || []
} }


// refresh paginations
generate_pages()

return [ return [
m('table', [ m('table', [
// always show table header // always show table header
@@ -34,7 +76,7 @@ export default initial_vnode => {
vnode.attrs.serial ? m('th.centered', '序号') : undefined, vnode.attrs.serial ? m('th.centered', '序号') : undefined,
...columns.map(column => m('th.centered', column.label)) ...columns.map(column => m('th.centered', column.label))
])), ])),
model.data(offset).length ? m('tbody', model.data(offset).map((row, i) => m('tr', [
model.data(offset, limit).length ? m('tbody', model.data(offset, limit).map((row, i) => m('tr', [
vnode.attrs.serial ? m('td.centered', offset+i+1) : undefined, vnode.attrs.serial ? m('td.centered', offset+i+1) : undefined,
...columns.map(column => { ...columns.map(column => {
let v = row[column.label] || '' let v = row[column.label] || ''
@@ -46,107 +88,16 @@ export default initial_vnode => {
}) })
]))) : m('', 'Empty') ]))) : m('', 'Empty')
]), ]),
/* _pages.length > 1 ?
m('.centered',
m('.pagination.centered', _pages.map((page, i) => page.show ? m('a', {
class: page.active ? 'active' : '',
onclick: e => {
_offset = i * vnode.attrs.options.paging.size
vnode.attrs.options.model.load({begin: i * vnode.attrs.options.paging.size, end: (i+1) * vnode.attrs.options.paging.size})
}
}, i + 1) : undefined))
)
: undefined*/
]
}
}
}

export const default1 = _ => {
let _columns = []
let _offset= 0
let _pages = []
let _model_slice = []

return {
view: vnode => {
// prepare columns by merging model.selects and columns config
_columns = Array.from(vnode.attrs.options.model.configs().selects, ([label, select]) => ({
label: select.alias || label,
tag: vnode.attrs.options.columns[label] && vnode.attrs.options.columns[label].tag
}))

if (vnode.attrs.options.model.ambient_changed())
_offset = 0

// prepare pages
if (vnode.attrs.options.paging && vnode.attrs.options.model.count) {
_offset = ~~_offset
let _active_page = _offset / vnode.attrs.options.paging.size
_pages = Array.from(Array(vnode.attrs.options.paging.size ? Math.floor(~~vnode.attrs.options.model.count / vnode.attrs.options.paging.size) + 1 : 0)).map((_,i) => _active_page == i ? {active: true} : {active: false})

if (_pages.length <= 10) {
_pages.forEach((page, i, pages) => pages[i].show = true)
} else {
let _showed_pages = new Set([0, _active_page, _pages.length -1])
let l = _active_page, r = _active_page
while (_showed_pages.size < 10) {
l -= 1
if (l < 0) {
_showed_pages.add(r+1)
r += 1
} else {
_showed_pages.add(l)
}
if (_showed_pages.size < 10) {
r += 1
if (r >= _pages.length) {
_showed_pages.add(l-1)
l -= 1
} else {
_showed_pages.add(r)
}
}
}
_showed_pages.forEach(v => _pages[v].show = true)
}
}

// visible model
function get_model_slice() {
return vnode.attrs.options.model.list.slice(_offset, _offset + ~~(vnode.attrs.options.paging && vnode.attrs.options.paging.size || 200))
}

return [
m('table', [
// always show table header
m('thead', m('tr', [
vnode.attrs.options.prepend_serial ? m('th.centered', '序号') : undefined,
..._columns.map(col => m('th.centered', col.label))
])),
get_model_slice().length ? m('tbody', get_model_slice().map((row, i) => m('tr', [
vnode.attrs.options.prepend_serial ? m('td.centered', _offset+i+1) : undefined,
..._columns.map(col => {
let v = row[col.label] || ''

if (typeof col.tag != 'undefined')
v = m(col.tag, v)

return m(`td${col.class || ''}`, v)
})
]))) : m('', 'Empty')
]),
_pages.length > 1 ?
pages.length > 1 ?
m('.centered', m('.centered',
m('.pagination.centered', _pages.map((page, i) => page.show ? m('a', {
m('.pagination.centered', pages.map((page, i) => page.show ? m('a', {
class: page.active ? 'active' : '', class: page.active ? 'active' : '',
onclick: e => { onclick: e => {
_offset = i * vnode.attrs.options.paging.size
vnode.attrs.options.model.load({begin: i * vnode.attrs.options.paging.size, end: (i+1) * vnode.attrs.options.paging.size})
offset = i*limit
model.select(offset, limit)
} }
}, i + 1) : undefined))
)
: undefined
}, i+1) : undefined))
) : undefined
] ]
} }
} }


+ 17
- 7
src/util/make_model.js Прегледај датотеку

@@ -30,7 +30,8 @@ export default (options={}) => {
endpoint: options.endpoint, endpoint: options.endpoint,
endpoint_type: options.endpoint.startsWith('/rpc') ? 'function' : 'relation', endpoint_type: options.endpoint.startsWith('/rpc') ? 'function' : 'relation',
// query part // query part
selects: options.selects
selects: options.selects,
order: options.order
} }


// private model cache & meta-info // private model cache & meta-info
@@ -61,11 +62,8 @@ export default (options={}) => {
limit = _cache.upstream_limit || _cache.count || Infinity limit = _cache.upstream_limit || _cache.count || Infinity


// be lazy 1: if the data is presented, return the value immediately // be lazy 1: if the data is presented, return the value immediately
//
// note that Array.every(list) == true if list is empty
let _portion = _cache.data.slice(offset, offset+limit)
if (_portion.length > 0 && _portion.every(data => data != undefined))
return Promise.resolve(_portion)
if (this.data(offset, limit).length > 0 && !this.data(offset, limit).includes(undefined))
return Promise.resolve(this.data(offset, limit))


// be lazy 2: if there is a promise, return it if ambient matches or // be lazy 2: if there is a promise, return it if ambient matches or
// cancel it // cancel it
@@ -83,11 +81,24 @@ export default (options={}) => {
queries: [ queries: [
// transform model state to postgest queries // transform model state to postgest queries
//...ambient_queries, //...ambient_queries,
// selects
...(_configs.selects ? [{ ...(_configs.selects ? [{
label: 'select', label: 'select',
value: _configs.selects.map(select => select.alias ? select.alias + ':' + select.label : select.label).join(',') value: _configs.selects.map(select => select.alias ? select.alias + ':' + select.label : select.label).join(',')
}] : []), }] : []),


// order
...(_configs.order ? [{
label: 'order',
value: _configs.order
.map(o => [
o.label,
o.direction,
o.nulls ? 'nulls'+o.nulls : ''
].filter(a => a).join('.'))
.join(',')
}] : []),

// limit/offset // limit/offset
offset == 0 ? undefined : {label: 'offset', value: offset}, offset == 0 ? undefined : {label: 'offset', value: offset},
limit == Infinity ? undefined : {label: 'limit', value: limit} limit == Infinity ? undefined : {label: 'limit', value: limit}
@@ -136,7 +147,6 @@ export const default1 = (args) => {
// private model configs // private model configs
let _configs = { let _configs = {
queries: args.queries || [], queries: args.queries || [],
order: args.order || []
} }
return { return {
// model & model state // model & model state


Loading…
Откажи
Сачувај