def display(self) -> None: html.text_input(self._varprefix + "name") html.br() html.begin_radio_group(horizontal=True) html.radiobutton(self._varprefix + "match", "exact", True, label=_("exact match")) html.radiobutton(self._varprefix + "match", "regex", False, label=_("regular expression, substring match")) html.end_radio_group() html.br() html.open_span(class_="min_max_row") html.write_text(_("Min. Version: ")) html.text_input(self._varprefix + "version_from", size=9) html.write_text(" ") html.write_text(_("Max. Vers.: ")) html.text_input(self._varprefix + "version_to", size=9) html.close_span() html.br() html.checkbox( self._varprefix + "negate", False, label=_("Negate: find hosts <b>not</b> having this package"))
def display(self, value: FilterHTTPVariables) -> None: html.text_input(self._varprefix + "name") html.br() display_filter_radiobuttons( varname=self._varprefix + "match", options=[ ("exact", _("exact match")), ("regex", _("regular expression, substring match")), ], default="exact", value=value, ) html.br() html.open_span(class_="min_max_row") html.write_text(_("Min. Version: ")) html.text_input( self._varprefix + "version_from", default_value=value.get(self._varprefix + "version_from", ""), size=9, ) html.write_text(" ") html.write_text(_("Max. Vers.: ")) html.text_input( self._varprefix + "version_to", default_value=value.get(self._varprefix + "version_from", ""), size=9, ) html.close_span() html.br() html.checkbox( self._varprefix + "negate", False, label=_("Negate: find hosts <b>not</b> having this package"), )
def _show_subtree(self, tree, path, show_host): # Check if we have an assumed state: comparing assumed state (tree[1]) with state (tree[0]) if tree[1] and tree[0] != tree[1]: addclass: Optional[str] = "assumed" effective_state = tree[1] else: addclass = None effective_state = tree[0] is_leaf = self._is_leaf(tree) if is_leaf: leaf = "leaf" mc = None else: leaf = "noleaf" mc = self._get_mousecode(path) classes = [ "bibox_box", leaf, "open" if self._is_open(path) else "closed", "state", "state%d" % effective_state["state"], addclass, ] omit = self._omit_root and len(path) == 1 if not omit: html.open_span( id_="%d:%s" % (self._expansion_level or 0, self._path_id(path)), class_=classes, onclick=mc, ) if is_leaf: self._show_leaf(tree, show_host) else: html.write_text(tree[2]["title"].replace(" ", " ")) html.close_span() if not is_leaf and not self._omit_content(path): html.open_span( class_="bibox", style="display: none;" if not self._is_open(path) and not omit else "", ) for node in tree[3]: new_path = path + [node[2]["title"]] self._show_subtree(node, new_path, show_host) html.close_span()
def _show_subtree(self, tree, path, show_host): if self._is_leaf(tree): self._show_leaf(tree, show_host) return html.open_span(class_="title") is_empty = len(tree[3]) == 0 if is_empty: mc = None else: mc = self._get_mousecode(path) css_class = "open" if self._is_open(path) else "closed" with self._show_node(tree, show_host, mousecode=mc, img_class=css_class): if tree[2].get("icon"): html.write_html(html.render_icon(tree[2]["icon"])) html.write_text(" ") if tree[2].get("docu_url"): html.icon_button( tree[2]["docu_url"], _("Context information about this rule"), "url", target="_blank", ) html.write_text(" ") html.write_text(tree[2]["title"]) if not is_empty: html.open_ul( id_="%d:%s" % (self._expansion_level or 0, self._path_id(path)), class_=["subtree", css_class], ) if not self._omit_content(path): for node in tree[3]: if not node[2].get("hidden"): new_path = path + [node[2]["title"]] html.open_li() self._show_subtree(node, new_path, show_host) html.close_li() html.close_ul() html.close_span()
def show(self, page_state: PageState) -> None: html.open_div(class_=self._get_css_classes(page_state)) html.open_div(class_="text") html.open_span() html.span(page_state.top_line, id_="page_state_top_line") html.span("", id_="headinfo") html.close_span() html.span(page_state.bottom_line) html.close_div() html.open_div(class_="icon_container") html.icon(page_state.icon_name, id_="page_state_icon") html.close_div() html.close_div()
def render_mobile_list(rows, view, group_cells, cells, num_columns, show_checkboxes): if not html.mobile: html.show_error(_("This view can only be used in mobile mode.")) return # Force relative timestamp always. This saves space. painter_options = PainterOptions.get_instance() painter_options.set("ts_format", "rel") html.open_ul(class_="mobilelist", **{"data-role": "listview"}) # Paint data rows for row in rows: html.open_li() rendered_cells = [cell.render(row) for cell in cells] if rendered_cells: # First cell (assumedly state) is left rendered_class, rendered_content = rendered_cells[0] html.open_p(class_=["ui-li-aside", "ui-li-desc", rendered_class]) html.write(rendered_content) html.close_p() if len(rendered_cells) > 1: content = HTML(" · ").join([ rendered_cell[1] for rendered_cell in rendered_cells[1:num_columns + 1] ]) html.h3(content) for rendered_cell, cell in zip( rendered_cells[num_columns + 1:], cells[num_columns + 1:]): rendered_class, rendered_content = rendered_cell html.open_p(class_="ui-li-desc") cell.paint_as_header() html.write_text(': ') html.open_span(class_=rendered_class) html.write(rendered_content) html.close_span() html.close_p() html.close_li() html.close_ul() html.javascript('$("ul.mobilelist a").attr("data-ajax", "false");')
def _render_headers(self, actions_enabled: bool, actions_visible: bool, empty_columns: List[bool]) -> None: if self.options["omit_headers"]: return table_id = self.id html.open_tr() first_col = True for nr, header in enumerate(self.headers): if self.options["omit_empty_columns"] and empty_columns[nr]: continue if header.help_txt: header_title: Union[int, HTML, str] = html.render_span( header.title, title=header.help_txt) else: header_title = header.title if not isinstance(header.css, list): css_class: CSSSpec = [header.css] else: css_class = header.css assert isinstance(css_class, list) css_class = [("header_%s" % c) for c in css_class if c is not None] if not self.options["sortable"] or not header.sortable: html.open_th(class_=css_class) else: css_class.insert(0, "sort") reverse = 0 sort = html.request.get_ascii_input('_%s_sort' % table_id) if sort: sort_col, sort_reverse = map(int, sort.split(',', 1)) if sort_col == nr: reverse = 1 if sort_reverse == 0 else 0 action_uri = html.makeactionuri([('_%s_sort' % table_id, '%d,%d' % (nr, reverse))]) html.open_th(class_=css_class, title=_("Sort by %s") % header.title, onclick="location.href='%s'" % action_uri) # Add the table action link if first_col: first_col = False if actions_enabled: if not header_title: header_title = " " # Fixes layout problem with white triangle if actions_visible: state = '0' help_txt = _('Hide table actions') img = 'table_actions_on' else: state = '1' help_txt = _('Display table actions') img = 'table_actions_off' html.open_div(class_=["toggle_actions"]) html.icon_button(html.makeuri([('_%s_actions' % table_id, state)]), help_txt, img, cssclass='toggle_actions') html.open_span() html.write(header_title) html.close_span() html.close_div() else: html.write(header_title) else: html.write(header_title) html.close_th() html.close_tr()
def _render_headers(self, actions_enabled, actions_visible, empty_columns): if self.options["omit_headers"]: return table_id = self.id html.open_tr() first_col = True for nr, (header, css, help_txt, sortable) in enumerate(self.headers): if self.options["omit_empty_columns"] and empty_columns[nr]: continue text = header if help_txt: header = '<span title="%s">%s</span>' % ( html.attrencode(help_txt), header) css_class = "header_%s" % css if css else None if not self.options["sortable"] or not sortable: html.open_th(class_=css_class) else: reverse = 0 sort = html.request.var('_%s_sort' % table_id) if sort: sort_col, sort_reverse = map(int, sort.split(',', 1)) if sort_col == nr: reverse = 1 if sort_reverse == 0 else 0 action_uri = html.makeactionuri([('_%s_sort' % table_id, '%d,%d' % (nr, reverse))]) html.open_th(class_=["sort", css_class], title=_("Sort by %s") % text, onclick="location.href='%s'" % action_uri) # Add the table action link if first_col: first_col = False if actions_enabled: if not header: header = " " # Fixes layout problem with white triangle if actions_visible: state = '0' help_txt = _('Hide table actions') img = 'table_actions_on' else: state = '1' help_txt = _('Display table actions') img = 'table_actions_off' html.open_div(class_=["toggle_actions"]) html.icon_button(html.makeuri([('_%s_actions' % table_id, state)]), help_txt, img, cssclass='toggle_actions') html.open_span() html.write(header) html.close_span() html.close_div() else: html.write(header) else: html.write(header) html.close_th() html.close_tr()
def render_snapin(self, snapin: UserSidebarSnapin) -> str: snapin_class = snapin.snapin_type name = snapin_class.type_name() snapin_instance = snapin_class() more_id = "sidebar_snapin_%s" % name show_more = config.user.get_show_more_setting(more_id) html.open_div(id_="snapin_container_%s" % name, class_=["snapin", ("more" if show_more else "less")]) self._render_snapin_styles(snapin_instance) # When not permitted to open/close snapins, the snapins are always opened if snapin.visible == SnapinVisibility.OPEN or not config.user.may( "general.configure_sidebar"): style = None else: style = "display:none" toggle_url = "sidebar_openclose.py?name=%s&state=" % name # If the user may modify the sidebar then add code for dragging the snapin head_actions: Dict[str, str] = {} if config.user.may("general.configure_sidebar"): head_actions = { "onmouseover": "document.body.style.cursor='move';", "onmouseout ": "document.body.style.cursor='';", "onmousedown": "cmk.sidebar.snapin_start_drag(event)", "onmouseup": "cmk.sidebar.snapin_stop_drag(event)" } html.open_div(class_=["head", snapin.visible.value], **head_actions) show_more = snapin_instance.has_show_more_items() may_configure = config.user.may("general.configure_sidebar") if show_more or may_configure: html.open_div(class_="snapin_buttons") if show_more: html.open_span(class_="moresnapin") html.more_button(more_id, dom_levels_up=4) html.close_span() if may_configure: # Button for closing (removing) a snapin html.open_span(class_="closesnapin") close_url = "sidebar_openclose.py?name=%s&state=off" % name html.icon_button( url=None, title=_("Remove this snapin"), icon="close", onclick="cmk.sidebar.remove_sidebar_snapin(this, '%s')" % close_url) html.close_span() html.close_div() # The heading. A click on the heading mini/maximizes the snapin toggle_actions: Dict[str, str] = {} if config.user.may("general.configure_sidebar"): toggle_actions = { "onclick": "cmk.sidebar.toggle_sidebar_snapin(this,'%s')" % toggle_url, "onmouseover": "this.style.cursor='pointer'", "onmouseout": "this.style.cursor='auto'" } html.b(textwrap.shorten(snapin_class.title(), width=27, placeholder="..."), class_=["heading"], **toggle_actions) if may_configure: # Icon for mini/maximizing html.span("", class_="minisnapin", title=_("Toggle this snapin"), onclick="cmk.sidebar.toggle_sidebar_snapin(this, '%s')" % toggle_url) # End of header html.close_div() # Now comes the content html.open_div(class_="content", id_="snapin_%s" % name, style=style) refresh_url = '' try: # TODO: Refactor this confusing special case. Add deddicated method or something # to let the snapins make the sidebar know that there is a URL to fetch. url = snapin_instance.show() if url is not None: # Fetch the contents from an external URL. Don't render it on our own. refresh_url = url html.javascript( "cmk.ajax.get_url(\"%s\", cmk.utils.update_contents, \"snapin_%s\")" % (refresh_url, name)) except Exception as e: logger.exception("error rendering snapin %s", name) write_snapin_exception(e) html.close_div() html.close_div() return refresh_url
def render_addto_popup_title(cls, title): html.open_li() html.open_span() html.write("%s:" % title) html.close_span() html.close_li()
def _show_node(self, tree, show_host, mousecode=None, img_class=None): # Check if we have an assumed state: comparing assumed state (tree[1]) with state (tree[0]) if tree[1] and tree[0] != tree[1]: addclass: Optional[str] = "assumed" effective_state = tree[1] else: addclass = None effective_state = tree[0] class_: List[Optional[str]] = [ "content", # "state", "state%d" % (effective_state["state"] if effective_state["state"] is not None else -1), addclass, ] html.open_span(class_=class_) html.write_text(self._render_bi_state(effective_state["state"])) html.close_span() if mousecode: if img_class: html.img( src=theme.url("images/tree_closed.svg"), class_=["treeangle", img_class], onclick=mousecode, ) html.open_span(class_=["content", "name"]) icon_name, icon_title = None, None if tree[0]["in_downtime"] == 2: icon_name = "downtime" icon_title = _("This element is currently in a scheduled downtime.") elif tree[0]["in_downtime"] == 1: # only display host downtime if the service has no own downtime icon_name = "derived_downtime" icon_title = _("One of the subelements is in a scheduled downtime.") if tree[0]["acknowledged"]: icon_name = "ack" icon_title = _("This problem has been acknowledged.") if not tree[0]["in_service_period"]: icon_name = "outof_serviceperiod" icon_title = _("This element is currently not in its service period.") if icon_name and icon_title: html.icon(icon_name, title=icon_title, class_=["icon", "bi"]) yield if mousecode: if str(effective_state["state"]) in tree[2].get("state_messages", {}): html.b(HTML("♦"), class_="bullet") html.write_text(tree[2]["state_messages"][str(effective_state["state"])]) html.close_span() output: HTML = cmk.gui.view_utils.format_plugin_output( effective_state["output"], shall_escape=config.escape_plugin_output ) if output: output = html.render_b(HTML("♦"), class_="bullet") + output else: output = HTML() html.span(output, class_=["content", "output"])