def ext_options(self, **kw): kw = Component.ext_options(self, **kw) # edge case of invalid extjs layout when user doesn't have permision to view vflex items. Ticket #2916 if getattr(self, 'vflex', False) and kw.get('region', "") != "center" and \ get_user_profile() and \ len([e for e in getattr(getattr(self, 'parent',None), "elements",[]) if e.get_view_permission(get_user_profile())]) == 1: kw['region'] = 'center' return kw
def ext_options(self, **kw): kw = Component.ext_options(self, **kw) # edge case of invalid extjs layout when user doesn't have permision to view vflex items. Ticket #2916 if getattr(self, 'vflex', False) and kw.get('region', "") != "center" and \ get_user_profile() and \ len([e for e in getattr(getattr(self, 'parent',None), "elements",[]) if e.get_view_permission(get_user_profile())]) == 1: kw['region'] = 'center' return kw
def get_view_permission(e): if isinstance( e, Permittable) and not e.get_view_permission(get_user_profile()): return False # e.g. pcsw.ClientDetail has a tab "Other", visible only to system # admins but the "Other" contains a GridElement RolesByPerson # which is not per se reserved for system admins. js of normal # users should not try to call on_master_changed() on it parent = e.parent while parent is not None: if isinstance(parent, Permittable) and not parent.get_view_permission( get_user_profile()): return False # bug 3 (bcss_summary) blog/2012/0927 parent = parent.parent return True
def get_view_permission(e): if isinstance(e, Permittable) and not e.get_view_permission( get_user_profile()): return False # e.g. pcsw.ClientDetail has a tab "Other", visible only to system # admins but the "Other" contains a GridElement RolesByPerson # which is not per se reserved for system admins. js of normal # users should not try to call on_master_changed() on it parent = e.parent while parent is not None: if isinstance(parent, Permittable) and not parent.get_view_permission( get_user_profile()): return False # bug 3 (bcss_summary) blog/2012/0927 parent = parent.parent return True
def write_lino_js(self, f): """ :param f: File object :return: 1 """ raise NotImplementedError("Need to implement a lino_web.js writing script") user_type = get_user_profile() context = dict( ext_renderer=self, site=settings.SITE, settings=settings, lino=lino, language=translation.get_language(), # ext_requests=constants, constants=constants, extjs=self.plugin, # 20171227 ) context.update(_=_) tpl = self.linolib_template() f.write(tpl.render(**context) + '\n') return 1
def lino_js_parts(self): user_type = get_user_profile() filename = 'lino_' if user_type is not None: filename += user_type.value + '_' filename += translation.get_language() + '.js' return ('cache', 'js', filename)
def write_lino_js(self, f): """ :param f: File object :return: 1 """ raise NotImplementedError( "Need to implement a lino_web.js writing script") user_type = get_user_profile() context = dict( ext_renderer=self, site=settings.SITE, settings=settings, lino=lino, language=translation.get_language(), # ext_requests=constants, constants=constants, extjs=self.plugin, # 20171227 ) context.update(_=_) tpl = self.linolib_template() f.write(tpl.render(**context) + '\n') return 1
def lino_js_parts(self): user_type = get_user_profile() filename = 'lino_' file_type = self.lino_web_template.rsplit(".")[-1] if user_type is not None: filename += user_type.value + '_' filename += translation.get_language() + '.' + file_type return ('cache', file_type, filename)
def lino_js_parts(self): user_type = get_user_profile() filename = 'lino_' file_type = self.lino_web_template.rsplit(".")[-1] if user_type is not None: filename += user_type.value + '_' filename += translation.get_language() + '.' + file_type return ('cache', file_type, filename)
def lino_js_parts_chunked(self, actorId): """ Like lino_js_parts, but for actor_level data""" user_type = get_user_profile() filename = 'Lino_' + actorId + "_" file_type = self.lino_web_template.rsplit(".")[-1] # json if user_type is not None: filename += user_type.value + '_' filename += translation.get_language() + '.' + file_type return ('cache', file_type, filename)
def declare_vars(v): """ Yields the Javascript lines that declare the given :class:`Variable` `v`. If `v` is a :class:`Component`, `list`, `tuple` or `dict` which contains other variables, recursively yields also the lines to declare these. """ if isinstance(v, (list, tuple)): for sub in v: for ln in declare_vars(sub): yield ln return if isinstance(v, dict): for sub in v.values(): for ln in declare_vars(sub): yield ln return if isinstance(v, VisibleComponent) and not v.get_view_permission( get_user_profile()): return if isinstance(v, Component): for sub in v.ext_options().values(): for ln in declare_vars(sub): yield ln # DON'T return elif isinstance(v, Value): # 20120616 if not v.is_visible(): return # ok = True for ln in declare_vars(v.value): yield ln # DON'T return if isinstance(v, Variable): # 20120616 if not v.is_visible(): return if v.declare_type == DECLARE_VAR: yield "var %s = %s;" % (v.ext_name, v.js_value()) elif v.declare_type == DECLARE_THIS: yield "this.%s = %s;" % (v.ext_name, v.js_value())
def declare_vars(v): """ Yields the Javascript lines that declare the given :class:`Variable` `v`. If `v` is a :class:`Component`, `list`, `tuple` or `dict` which contains other variables, recursively yields also the lines to declare these. """ if isinstance(v, (list, tuple)): for sub in v: for ln in declare_vars(sub): yield ln return if isinstance(v, dict): for sub in list(v.values()): for ln in declare_vars(sub): yield ln return if isinstance(v, VisibleComponent) and not v.get_view_permission( get_user_profile()): return if isinstance(v, Component): for sub in list(v.ext_options().values()): for ln in declare_vars(sub): yield ln # DON'T return elif isinstance(v, Value): # 20120616 if not v.is_visible(): return # ok = True for ln in declare_vars(v.value): yield ln # DON'T return if isinstance(v, Variable): # 20120616 if not v.is_visible(): return if v.declare_type == DECLARE_VAR: yield "var %s = %s;" % (v.ext_name, v.js_value()) elif v.declare_type == DECLARE_THIS: yield "this.%s = %s;" % (v.ext_name, v.js_value())
def write_lino_js(self, f): """ :param f: File object :return: 1 """ choicelists_data = { # ID: [{"value": py2js(c[0]).strip('"'), "text": py2js(c[1]).strip('"')} for c in cl.get_choices()] for ID: [{ "value": c[0].value, "text": str(c[1]) } for c in cl.get_choices()] for ID, cl in kernel.CHOICELISTS.items() } actions = set() for rpt in self.actors_list: # rh = rpt.get_handle() #for getting bound actor, not needed. for ba in rpt.get_actions(): if ba.action not in actions: actions.add(ba.action) self.serialise_js_code = True f.write( py2js( dict( actions={a.action_name: a for a in actions}, # actors={a.actor_id: a for a in self.actors_list}, menu=settings.SITE.get_site_menu(get_user_profile()), choicelists=choicelists_data, suggestors=list(settings.SITE.plugins.memo.parser. suggesters.keys()) # [#,@] keytriggers ), compact=not settings.SITE.is_demo_site)) self.serialise_js_code = False return 1
def is_visible(self): if self.hidden: return False return self.get_view_permission(get_user_profile())
def py2js(v, compact=True): """Note that None values are rendered as ``null`` (not ``undefined``. """ # assert _for_user_profile is not None # logger.debug("py2js(%r)",v) for cv in CONVERTERS: v = cv(v) # if isinstance(v,LanguageInfo): # return v.django_code if isinstance(v, Value): return v.as_ext() # v = v.as_ext() # if not isinstance(v, basestring): # raise Exception("20120121b %r is of type %s" % (v,type(v))) # return v if isinstance(v, Promise): # v = force_text(v) return json.dumps(force_text(v.encode('utf8'))) if isinstance(v, types.GeneratorType): return "".join([py2js(x, compact=compact) for x in v]) if etree.iselement(v): return json.dumps(force_text(etree.tostring(v))) # try: # return json.dumps(force_text(etree.tostring(v))) # except Exception as e: # return json.dumps("Failed to render {!r} : {}".format(v, e)) # if type(v) is types.GeneratorType: # raise Exception("Please don't call the generator function yourself") # return "\n".join([ln for ln in v]) if callable(v): # print 20120114, repr(v) # raise Exception("Please call the function yourself") return "\n".join([ln for ln in v()]) if isinstance(v, js_code): return str(v.s) # v.s might be a unicode if v is None: # return 'undefined' return 'null' if isinstance(v, (list, tuple)): # (types.ListType, types.TupleType): elems = [py2js(x, compact=compact) for x in v if (not isinstance(x, VisibleComponent)) or x.get_view_permission(get_user_profile())] sep = ", " if compact else ", \n" return "[ %s ]" % sep.join(elems) if isinstance(v, dict): items = [ # i for i in sorted(v.items(), key=lambda x: str(x)) # i for i in sorted(v.items()) i for i in v.items() if (not isinstance(v, VisibleComponent)) or v.get_view_permission(get_user_profile())] if six.PY2: # "sorted(v.items())" without sortkey caused TypeError when # the dictionary contained a mixture of unicode and # future.types.newstr objects. def sortkey(x): if isinstance(x[0], newstr): return six.text_type(x[0]) return x[0] else: def sortkey(x): return x[0] items = sorted(items, key=sortkey) # try: # items = sorted(items, key=sortkey) # except TypeError as e: # raise TypeError("Failed to sort {0!r} : {1}".format(items, e)) sep = ", " if compact else ", \n" return "{ %s }" % sep.join( ["%s: %s" % (py2js(k, compact=compact), py2js(i, compact=compact)) for k, i in items]) if isinstance(v, bool): # types.BooleanType: return str(v).lower() if isinstance(v, Quantity): return '"%s"' % v if isinstance(v, (int, decimal.Decimal, fractions.Fraction)): return str(v) if isinstance(v, IncompleteDate): return '"%s"' % v.strftime(settings.SITE.date_format_strftime) if isinstance(v, datetime.datetime): return '"%s"' % v.strftime(settings.SITE.datetime_format_strftime) if isinstance(v, datetime.time): return '"%s"' % v.strftime(settings.SITE.time_format_strftime) if isinstance(v, datetime.date): if v.year < 1900: v = IncompleteDate.from_date(v) return '"%s"' % v.strftime(settings.SITE.date_format_strftime) return '"%s"' % v.strftime(settings.SITE.date_format_strftime) if isinstance(v, float): return repr(v) # return json.encoder.encode_basestring(v) # print repr(v) # http://docs.djangoproject.com/en/dev/topics/serialization/ # if not isinstance(v, (str,unicode)): # raise Exception("20120121 %r is of type %s" % (v,type(v))) return json.dumps(v, sort_keys=True, indent=4, separators=(',', ': ') )
def is_visible(self): if self.hidden: return False return self.get_view_permission(get_user_profile())
def py2js_converter(self, v): """ Additional converting logic for serializing Python values to json. """ if v is settings.SITE.LANGUAGE_CHOICES: return js_code('LANGUAGE_CHOICES') if isinstance(v, choicelists.Choice): """ This is special. We don't render the text but the value. """ return v.value if isinstance(v, models.Model): return v.pk if isinstance(v, Exception): return str(v) if isinstance(v, Menu): if v.parent is None: return v.items # kw.update(region='north',height=27,items=v.items) # return py2js(kw) return dict(text=v.label, menu=dict(items=v.items)) if isinstance(v, MenuItem): if v.instance is not None: h = self.instance_handler(None, v.instance, None) assert h is not None js = "%s" % h return self.handler_item(v, h, None) elif v.bound_action is not None: if v.params: ar = v.bound_action.request(**v.params) js = self.request_handler(ar) else: js = self.action_call(None, v.bound_action, {}) return self.handler_item(v, js, v.help_text) elif v.javascript is not None: js = "%s" % v.javascript return self.handler_item(v, js, v.help_text) elif v.href is not None: url = v.href # ~ elif v.request is not None: # ~ raise Exception("20120918 request %r still used?" % v.request) # ~ url = self.get_request_url(v.request) else: # a separator # ~ return dict(text=v.label) return v.label # ~ url = self.build_url('api',v.action.actor.app_label,v.action.actor.__name__,fmt=v.action.name) if v.parent.parent is None: # special case for href items in main menubar return dict( xtype='button', text=v.label, # ~ handler=js_code("function() { window.location='%s'; }" % url)) handler=js_code("function() { Lino.load_url('%s'); }" % url)) return dict(text=v.label, href=url) if issubclass(v.__class__, LayoutElement): # Layout elems result = dict(label=v.get_label(), repr=repr(v), react_name=v.__class__.__name__ ) # Used for choosing correct react component if hasattr(v, "elements"): # dd result['items'] = [ e for e in v.elements if e.get_view_permission(get_user_profile()) ] result.update( obj2dict( v, "fields_index fields_index_hidden editable vertical hpad is_fieldset name width preferred_width\ hidden value hflex vflex")) # result["width"] = v.width or v.preferred_width # Slave tables if hasattr(v, "actor"): # reference to actor data for slave-grids result.update(obj2dict( v.actor, "actor_id")) # to get siteDate layout index # if hasattr(v, "get_field_options"): if issubclass(v.__class__, FieldElement): result.update(field_options=v.get_field_options()) result.update(help_text=v.field.help_text) return result if isinstance(v, LayoutHandle): # Layout entry-point return dict(main=v.main, window_size=v.layout.window_size) if isinstance(v, Action): # todo include all aux info # todo include grid info # todo refactor this into a all_actions object and have the bound actions ref it to reduse json size result = dict( an=v.action_name, label=v.get_label( ), # todo fix this, this is a readable action, not ID for the action window_action=v.is_window_action(), http_method=v.http_method, ) # if v.show_in_bbar: result["bbar"] = True # not needed if v.preprocessor: result["preprocessor"] = v.preprocessor if v.combo_group: result["combo_group"] = v.combo_group if v.select_rows: result['select_rows'] = v.select_rows if v.submit_form_data: result['submit_form_data'] = True if v.button_text: result['button_text'] = v.button_text icon = self.get_action_icon(v) if icon: result['icon'] = icon return result if isinstance(v, BoundAction): # todo include all aux info # todo include grid info # todo refactor this into a all_actions object and have the bound actions ref it to reduse json size result = dict( an=v.action.action_name, window_layout=v.get_layout_handel(), ) # if v.action.show_in_bbar: result["bbar"] = True # not needed if v.action.window_type: tba = [] combo_group = None for ba in v.actor.get_toolbar_actions(v.action): if ba.action.combo_group == combo_group and combo_group is not None: previous = tba.pop() if not isinstance(previous, list): previous = [previous] previous.append(ba.action.action_name) tba.append(previous) else: # is normal tba.append(ba.action.action_name) combo_group = ba.action.combo_group result["toolbarActions"] = tba return result if isclass(v) and issubclass(v, Actor): result = dict( id=v.actor_id, ba=v._actions_dict, label=v.get_actor_label(), slave=bool(v.master), editable=v.editable, # [py2js(b) for b in v.actions.items()] ) # grids if hasattr(v.get_handle(), "get_columns"): result['col'] = v.get_handle().get_columns() index_mod = 0 for c in result['col']: c.fields_index = find(v.get_handle().store.list_fields, c.field.name, key=lambda f: f.name) + index_mod if isinstance(c, ComboFieldElement) and not isinstance( c, SimpleRemoteComboFieldElement): # Skip the data value for multi value columns, such as choices and FK fields. # use c.fields_index -1 for data value c.fields_index_hidden = c.fields_index + 1 index_mod += 1 result.update(obj2dict(v.get_handle().store, "pk_index")) # Data index which is the PK result.update( obj2dict( v, "preview_limit " # number of rows to render # if 0 no paginator. "use_detail_param_panel " # show PV panel in detail "use_detail_params_value " # in grid, use parrent PV values "hide_top_toolbar " # No selection and toolbar "use_detail_params_value " "react_responsive " "react_big_search " "display_mode " "max_render_depth " "simple_slavegrid_header " "paginator_template " "hide_if_empty " "borderless_list_mode ")) card_layout = getattr(v, "card_layout", None) if card_layout is not None: result.update(card_layout=card_layout.get_layout_handle()) # mt + slave-tables chooser_dict = getattr(v.model, "_choosers_dict", {}) if chooser_dict: result.update( chooser_dict={ fn: [cf.name for cf in c.context_fields] for fn, c in chooser_dict.items() }) if settings.SITE.is_installed('contenttypes') and getattr( v, 'model', None) is not None and hasattr( v.model, "_meta"): # Perhaps I should have the model also be py2js'd? result.update( content_type=ContentType.objects.get_for_model(v.model).pk) for a in "detail_action insert_action default_action".split(" "): if hasattr(v, a) and getattr(v, a) is not None: result.update({a: getattr(v, a).action.action_name}) if v.params_layout is not None: # Param field array and layout struct result.update( pv_layout=v.params_layout.get_layout_handle(), pv_fields=[ f.name for f in v.params_layout.params_store.param_fields ], ) return result if isinstance(v, js_code) and getattr(self, "serialise_js_code", False): # Convert js_code into strings so they are serialised. rather than displayed w/o quotes return str(v.s) return v
def js_render_FormPanelSubclass(self, dh): tbl = dh.layout._datasource if not dh.main.get_view_permission(get_user_profile()): msg = "No view permission for main panel of %s :" % \ dh.layout._formpanel_name msg += " main requires %s (actor %s requires %s)" % ( dh.main.required_roles, tbl, tbl.required_roles) # ~ raise Exception(msg) logger.warning(msg) print(20150717, msg) return yield "" # yield "Lino.%s = Ext.extend(Lino.FormPanel,{" % \ # dh.layout._formpanel_name yield "Ext.define('Lino.%s', { extend : 'Lino.FormPanel'," % \ dh.layout._formpanel_name yield " layout: 'fit'," yield " auto_save: true," if dh.layout.window_size and dh.layout.window_size[1] == 'auto': yield " autoHeight: true," if settings.SITE.is_installed('contenttypes') and issubclass( tbl, dbtables.Table): yield " content_type: %s," % py2js( ContentType.objects.get_for_model(tbl.model).pk) if not tbl.editable: yield " disable_editing: true," if not tbl.auto_apply_params: yield " auto_apply_params: false," if dh.layout._formpanel_name.endswith('.InsertFormPanel'): yield " default_record_id: -99999," yield " initComponent : function() {" # 20140503 yield " var containing_panel = this;" # yield "// user user_type: %s" % jsgen._for_user_profile lc = 0 for ln in jsgen.declare_vars(dh.main): yield " " + ln lc += 1 if lc == 0: raise Exception("%r of %s has no variables" % (dh.main, dh)) yield " this.items = %s;" % dh.main.as_ext() # ~ if issubclass(tbl,tables.AbstractTable): if True: yield " this.before_row_edit = function(record) {" for ln in self.before_row_edit(dh.main): yield " " + ln yield " }" on_render = self.build_on_render(dh.main) if on_render: yield " this.onRender = function(ct, position) {" for ln in on_render: yield " " + ln yield " Lino.%s.superclass.onRender.call(this, ct, position);" % \ dh.layout._formpanel_name # yield " this.callSuper(ct, position);" yield " }" # yield " Lino.%s.superclass.initComponent.call(this);" % \ # dh.layout._formpanel_name yield " this.callSuper();" # Add a change listener to active fields. This which will # cause automatic form submit when some actiove field is # changed. if dh.layout._formpanel_name.endswith('.DetailFormPanel'): if tbl.active_fields: yield ' // active_fields:' for name in tbl.active_fields: e = dh.main.find_by_name(name) if e is not None: # 20120715 if True: # see actions.ValidateForm f = 'function(){ this.save() }' else: f = 'function(){ this.validate_form() }' yield ' %s.on("change", %s, this);' % (py2js(e), f) yield " }" yield "});" yield ""
def py2js(v): """Note that None values are rendered as ``null`` (not ``undefined``. """ # assert _for_user_profile is not None # logger.debug("py2js(%r)",v) for cv in CONVERTERS: v = cv(v) # if isinstance(v,LanguageInfo): # return v.django_code if isinstance(v, Value): return v.as_ext() # v = v.as_ext() # if not isinstance(v, basestring): # raise Exception("20120121b %r is of type %s" % (v,type(v))) # return v if isinstance(v, Promise): # v = force_text(v) return json.dumps(force_text(v.encode('utf8'))) if isinstance(v, types.GeneratorType): return "".join([py2js(x) for x in v]) if etree.iselement(v): return json.dumps(force_text(etree.tostring(v))) # try: # return json.dumps(force_text(etree.tostring(v))) # except Exception as e: # return json.dumps("Failed to render {!r} : {}".format(v, e)) # if type(v) is types.GeneratorType: # raise Exception("Please don't call the generator function yourself") # return "\n".join([ln for ln in v]) if callable(v): # print 20120114, repr(v) # raise Exception("Please call the function yourself") return "\n".join([ln for ln in v()]) if isinstance(v, js_code): return str(v.s) # v.s might be a unicode if v is None: # return 'undefined' return 'null' if isinstance(v, (list, tuple)): # (types.ListType, types.TupleType): elems = [py2js(x) for x in v if (not isinstance(x, VisibleComponent)) or x.get_view_permission(get_user_profile())] return "[ %s ]" % ", ".join(elems) if isinstance(v, dict): items = [ # i for i in sorted(v.items(), key=lambda x: str(x)) # i for i in sorted(v.items()) i for i in v.items() if (not isinstance(v, VisibleComponent)) or v.get_view_permission(get_user_profile())] if six.PY2: # "sorted(v.items())" without sortkey caused TypeError when # the dictionary contained a mixture of unicode and # future.types.newstr objects. def sortkey(x): if isinstance(x[0], newstr): return six.text_type(x[0]) return x[0] else: def sortkey(x): return x[0] items = sorted(items, key=sortkey) # try: # items = sorted(items, key=sortkey) # except TypeError as e: # raise TypeError("Failed to sort {0!r} : {1}".format(items, e)) return "{ %s }" % ", ".join( ["%s: %s" % (py2js(k), py2js(i)) for k, i in items]) if isinstance(v, bool): # types.BooleanType: return str(v).lower() if isinstance(v, Quantity): return '"%s"' % v if isinstance(v, (int, decimal.Decimal, fractions.Fraction)): return str(v) if isinstance(v, IncompleteDate): return '"%s"' % v.strftime(settings.SITE.date_format_strftime) if isinstance(v, datetime.datetime): return '"%s"' % v.strftime(settings.SITE.datetime_format_strftime) if isinstance(v, datetime.time): return '"%s"' % v.strftime(settings.SITE.time_format_strftime) if isinstance(v, datetime.date): if v.year < 1900: v = IncompleteDate.from_date(v) return '"%s"' % v.strftime(settings.SITE.date_format_strftime) return '"%s"' % v.strftime(settings.SITE.date_format_strftime) if isinstance(v, float): return repr(v) # return json.encoder.encode_basestring(v) # print repr(v) # http://docs.djangoproject.com/en/dev/topics/serialization/ # if not isinstance(v, (str,unicode)): # raise Exception("20120121 %r is of type %s" % (v,type(v))) return json.dumps(v)