nulib: afficher les lignes d'action

This commit is contained in:
Jephté Clain 2018-05-09 00:18:25 +04:00
parent c7286d1406
commit e0d6910271
4 changed files with 110 additions and 45 deletions

View File

@ -1,2 +1,5 @@
eclipse.preferences.version=1 eclipse.preferences.version=1
encoding//python/nulib/web/bootstrap.py=utf-8
encoding//python/nulib/web/model.py=utf-8
encoding//python/nulib/web/ui.py=utf-8
encoding/<project>=UTF-8 encoding/<project>=UTF-8

View File

@ -11,12 +11,12 @@ __all__ = (
import sys, traceback import sys, traceback
from types import StringType from types import StringType
from ..base import isseq, seqof, Undef from ..base import Undef, isseq, seqof
from ..ext import web from ..ext import web
from . import ui from . import ui
from .api import _ensure_session, u, uval, uval_would_escape from .api import _ensure_session, u, uval, uval_would_escape
from .model import Row, TableSchema from .model import Row, RowSchema, TableSchema
from .ui import Action, litteral, p from .ui import Action, litteral, p
def load(prefix=None, icons=True, charset="utf-8"): def load(prefix=None, icons=True, charset="utf-8"):
@ -54,33 +54,32 @@ TRD_CLASS_MAP = dict(
warning="warning", warn="warning", notice="warning", warning="warning", warn="warning", notice="warning",
danger="danger", error="danger", danger="danger", error="danger",
) )
def trd_joinc(css): def trd_joinc(css, base_css=None):
if css is Undef: css = None if css is Undef: css = None
if type(css) is StringType: if type(css) is StringType: css = css.split(",")
css = css.split(",") if type(base_css) is StringType: base_css = base_css.split(",")
classes = [] classes = list(seqof(base_css))
for css in seqof(css): for css in seqof(css):
classes.append(TRD_CLASS_MAP.get(css, css)) classes.append(TRD_CLASS_MAP.get(css, css))
css = " ".join(classes) css = " ".join(classes)
return css return css
def td(value, schema=None, css=Undef, tag=Undef, **kw): def td(value, schema=None, css=Undef, tag=Undef, **kw):
css = Undef.sa(css, kw, 'c') css = Undef.sa(css, kw, 'c', None)
value = uval(value) if schema: value = schema.html(value)
if schema: else: value = uval(value)
value = schema.html(value) css = trd_joinc(css, schema.css(value) if schema else None)
if css is Undef: css = schema.css(value)
if tag is Undef: tag = "td" if tag is Undef: tag = "td"
css = trd_joinc(css)
return u"<%s%s>%s</%s>" % (tag, ui.classif(css), value, tag) return u"<%s%s>%s</%s>" % (tag, ui.classif(css), value, tag)
def tr(values, schema=None, css=Undef, celltag=Undef, **kw): def tr(values, schema=None, css=Undef, actions=Undef, celltag=Undef, **kw):
css = Undef.sa(css, kw, 'c') css = Undef.sa(css, kw, 'c', None)
tdschema = lambda value, index: None actions = Undef.sa(actions, kw, None, None)
if schema is not None: if schema: tdschema = lambda value, index: schema.col_schema(value, index)
if css is Undef: css = schema.css(values) else: tdschema = lambda value, index: None
tdschema = lambda value, index: schema.cell_schema(value, index) css = trd_joinc(css, schema.css(values) if schema else None)
css = trd_joinc(css) if actions and actions != True:
css = ui.addclassif("action-tr", True, css)
lines = [] lines = []
lines.append(u"<tr%s>" % ui.classif(css)) lines.append(u"<tr%s>" % ui.classif(css))
index = 0 index = 0
@ -98,6 +97,18 @@ def tr(values, schema=None, css=Undef, celltag=Undef, **kw):
for value in values: for value in values:
lines.append(td(value, tdschema(value, index), tag=celltag)) lines.append(td(value, tdschema(value, index), tag=celltag))
index += 1 index += 1
if actions == True:
lines.append(td("Action", tag=celltag))
elif actions:
cell = []
cell.append(u"""<div class="action-links invisible">""")
for action in seqof(actions):
if schema:
action = action.update_query(schema.pk_dict(values))
cell.append(u"""<a href="%s"%s>%s</a>""" % (action.url, ui.classif(action.css), action.text))
cell.append(u"""</div>""")
lines.append(td(litteral("".join(cell)), tag=celltag))
pass
lines.append(u"</tr>") lines.append(u"</tr>")
return u"\n".join(lines) return u"\n".join(lines)
@ -108,30 +119,52 @@ TABLE_CLASS_MAP = dict(
hover="table-hover", h="table-hover", hover="table-hover", h="table-hover",
condensed="table-condensed", c="table-condensed", condensed="table-condensed", c="table-condensed",
) )
def table_joinc(css): def table_joinc(css, base_css=None):
if css is Undef: css = None if css is Undef: css = None
if type(css) is StringType: if type(css) is StringType: css = css.split(",")
css = css.split(",") if type(base_css) is StringType: base_css = base_css.split(",")
classes = ["table"] classes = ["table"]
classes.extend(seqof(base_css))
for css in seqof(css): for css in seqof(css):
classes.append(TABLE_CLASS_MAP.get(css, css)) classes.append(TABLE_CLASS_MAP.get(css, css))
css = " ".join(classes) css = " ".join(classes)
return css return css
def table(rows, schema=None, css=Undef, **kw): def tablejs(schema=None, jquery=False, script=False):
css = Undef.sa(css, kw, 'c') if schema and not schema.actions: return u""
if script: jquery = True
lines = []
lines.append(u"""<style type="text/css">
.action-links a { margin-right: 0.5em; }
</style>""")
if script: lines.append(u"""<script type="text/javascript">""")
if jquery: lines.append(u"""jQuery.noConflict()(function($) {""")
lines.append(u"""$(".action-tr").hover(
function() {
$(this).find(".action-links").removeClass("invisible");
}, function() {
$(this).find(".action-links").addClass("invisible");
});""")
if jquery: lines.append(u"""});""")
if script: lines.append(u"""</script>""")
return u"\n".join(lines)
def table(rows, schema=None, css=Undef, js=False, **kw):
css = Undef.sa(css, kw, 'c', None)
if schema is None: schema = TableSchema.parse(rows) if schema is None: schema = TableSchema.parse(rows)
elif isseq(schema): schema = TableSchema(schema) elif isseq(schema): schema = TableSchema(schema)
if css is Undef: css = schema.css(rows) css = table_joinc(css, schema.css())
css = table_joinc(css)
lines = [] lines = []
if js: lines.append(tablejs(schema, script=True))
lines.append(u"<table%s>" % ui.classif(css)) lines.append(u"<table%s>" % ui.classif(css))
lines.append(u"<thead>") lines.append(u"<thead>")
lines.append(tr(schema.headers(), schema.header_row_schema(), celltag="th")) lines.append(tr(schema.headers(), schema.header_row_schema(),
actions=True if schema.actions else False, celltag="th"))
lines.append(u"</thead><tbody>") lines.append(u"</thead><tbody>")
index = 0 index = 0
for row in rows: for row in rows:
lines.append(tr(row, schema.body_row_schema(index))) lines.append(tr(row, schema.body_row_schema(index),
actions=schema.actions))
index += 1 index += 1
lines.append(u"</tbody>") lines.append(u"</tbody>")
lines.append(u"</table>") lines.append(u"</table>")
@ -209,13 +242,13 @@ class Menu(ui.Menu):
lines = [] lines = []
if self.__is_navbar_fixed(navbar_type): if self.__is_navbar_fixed(navbar_type):
lines.append(u"""<style type="text/css">body { margin-top: 50px; }</style>""") lines.append(u"""<style type="text/css">body { margin-top: 50px; }</style>""")
css = u'' css = u"navbar navbar-default"
css = ui.addclassif("navbar-fixed-top", self.__is_navbar_fixed(navbar_type), css) css = ui.addclassif("navbar-fixed-top", self.__is_navbar_fixed(navbar_type), css)
css = ui.addclassif("navbar-static-top", self.__is_navbar_static(navbar_type), css) css = ui.addclassif("navbar-static-top", self.__is_navbar_static(navbar_type), css)
if self.profiles is not None and self.sel_profile is not None: if self.profiles is not None and self.sel_profile is not None:
css = ui.addclassif("%s-profile" % self.sel_profile, None, css) css = ui.addclassif("%s-profile" % self.sel_profile, None, css)
css = ui.addclassif(self.css, None, css) css = ui.addclassif(self.css, None, css)
lines.append(u"""<div class="navbar navbar-default%s" role="navigation">""" % css) lines.append(u"""<div class="%s" role="navigation">""" % css)
lines.append(u"""<div class="container%s"> lines.append(u"""<div class="container%s">
<div class="navbar-header"> <div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">

View File

@ -3,7 +3,10 @@
__all__ = ( __all__ = (
'LazyObject', 'LazyObject',
'dbconfig', 'fixsqlite', 'lazydb', 'oradbinfos', 'dbconfig', 'fixsqlite', 'lazydb', 'oradbinfos',
'incd', 'excd', 'ColSchema', 'Col', 'Row', 'RowCtl', 'ColSchema', 'Col',
'RowSchema', 'Row', 'RowCtl',
'TableSchema',
'incd', 'excd',
'Migration', 'Migration',
) )
@ -111,44 +114,55 @@ class ColSchema(odict):
return self.format(value, index) return self.format(value, index)
def html(self, value, index=Undef): def html(self, value, index=Undef):
link = uval(self.link) link = uval(self.link)
value = self.format(value, index) value = uval(self.format(value, index))
if link is None: return value if link is None: return value
else: return u'<a href="%s">%s</a>' % (link, value) else: return u'<a href="%s">%s</a>' % (link, value)
class Col(odict): class Col(odict):
def __init__(self, key, title=Undef, schema=Undef, formatter=Undef, link=Undef, **kw): def __init__(self, key, text=Undef, schema=Undef, formatter=Undef, link=Undef, **kw):
title = Undef.sa(title, kw, 't', None) text = Undef.sa(text, kw, 't', None)
schema = Undef.sa(schema, kw, 's', None) schema = Undef.sa(schema, kw, 's', None)
formatter = Undef.sa(formatter, kw, 'f') formatter = Undef.sa(formatter, kw, 'f')
link = Undef.sa(link, kw, 'u') link = Undef.sa(link, kw, 'u')
super(Col, self).__init__(**kw) super(Col, self).__init__(**kw)
if title is None: title = key if text is None: text = key
if schema is None and (formatter is not Undef or link is not Undef): if schema is None and (formatter is not Undef or link is not Undef):
schema = ColSchema(formatter, link) schema = ColSchema(formatter, link)
self.key = key self.key = key
self.title = title self.text = text
self.schema = schema self.schema = schema
def geti(values, index): def geti(values, index):
return values[index] if index >= 0 and index < len(values) else None return values[index] if index >= 0 and index < len(values) else None
class RowSchema(odict): class RowSchema(odict):
def __init__(self, cols=Undef, **kw): def __init__(self, cols=Undef, pks=Undef, actions=Undef, **kw):
cols = seqof(Undef.sa(cols, kw, None, None)) cols = seqof(Undef.sa(cols, kw, None, None))
pks = seqof(Undef.sa(pks, kw, 'pk', None))
actions = seqof(Undef.sa(actions, kw, None, None))
super(RowSchema, self).__init__(**kw) super(RowSchema, self).__init__(**kw)
self.__dict__['overlays'] = []
self.cols = cols self.cols = cols
self.pks = pks
self.actions = actions
def col(self, index=Undef): def col(self, index=Undef):
if index is not Undef: if index is not Undef:
return geti(self.cols, index) return geti(self.cols, index)
return None return None
def cell_schema(self, value=Undef, index=Undef): def col_schema(self, value=Undef, index=Undef):
if index is not Undef: if index is not Undef:
col = geti(self.cols, index) col = geti(self.cols, index)
if col is not None: return col.schema if col is not None: return col.schema
return None return None
def pk_dict(self, values):
d = {}
for pk in self.pks:
d[pk] = values[pk]
return d
def css(self, value=Undef): def css(self, value=Undef):
return None return None
@ -227,21 +241,28 @@ class TableSchema(odict):
cols = [Col(key) for key in _firstof(rows)] if rows else Undef cols = [Col(key) for key in _firstof(rows)] if rows else Undef
return TableSchema(cols) return TableSchema(cols)
def __init__(self, cols=Undef, **kw): def __init__(self, cols=Undef, pks=Undef, actions=Undef, **kw):
cols = seqof(Undef.sa(cols, kw, None, None)) cols = seqof(Undef.sa(cols, kw, None, None))
pks = seqof(Undef.sa(pks, kw, 'pk', None))
actions = seqof(Undef.sa(actions, kw, None, None))
super(TableSchema, self).__init__(**kw) super(TableSchema, self).__init__(**kw)
self.cols = cols self.cols = cols
self.pks = pks
self.actions = actions
self.row_schemas = {} self.row_schemas = {}
self.row_schemas['header'] = RowSchema(cols) self.row_schemas['header'] = RowSchema(cols, pks, actions)
self.row_schemas['body'] = RowSchema(cols) self.row_schemas['body'] = RowSchema(cols, pks, actions)
def headers(self): def headers(self):
return [col.title for col in self.cols] return [col.text for col in self.cols]
def header_row_schema(self): def header_row_schema(self):
return self.row_schemas["header"] return self.row_schemas["header"]
def body_row_schema(self, index): def body_row_schema(self, index):
return self.row_schemas["body"] return self.row_schemas["body"]
def css(self):
return None
def incd(fd, *names): def incd(fd, *names):
td = dict() td = dict()
if not names: if not names:

View File

@ -34,9 +34,10 @@ def classif(c, b=None):
return u' class="%s"' % c if b else u'' return u' class="%s"' % c if b else u''
def addclassif(c, b=None, prefix=None): def addclassif(c, b=None, prefix=None):
if b is None: b = c if b is None: b = c
if prefix is None: prefix = u'' if not prefix: prefix = u''
if b: return u'%s %s' % (prefix, c) if not b: return prefix
else: return prefix elif prefix: return u'%s %s' % (prefix, c)
else: return c
def favicon(href): def favicon(href):
return ur'<link rel="shortcut icon" href="%s" />' % href return ur'<link rel="shortcut icon" href="%s" />' % href
@ -168,6 +169,13 @@ class Action(odict):
self.__update_url(*['%s_%s' % (profile, key) for key in ('url', 'query', 'baseurl')]) self.__update_url(*['%s_%s' % (profile, key) for key in ('url', 'query', 'baseurl')])
self.__update_url(*['to_%s_%s' % (profile, key) for key in ('url', 'query', 'baseurl')]) self.__update_url(*['to_%s_%s' % (profile, key) for key in ('url', 'query', 'baseurl')])
def update_query(self, query):
return self.__class__(
self.url, self.text, self.id, self.in_profiles, self.css, self.accesskey,
query,
self.title, self.method,
)
def __get_key(self, key, profile=None, to=False): def __get_key(self, key, profile=None, to=False):
if profile is not None: if profile is not None:
pkey = '%s%s_%s' % ('to_' if to else '', profile, key) pkey = '%s%s_%s' % ('to_' if to else '', profile, key)