def show(self) -> None: for topic, bookmarks in self._get_bookmarks_by_topic(): with foldable_container( treename="bookmarks", id_=topic, isopen=False, title=topic, indent=False, icon="foldable_sidebar", ): for bookmark in bookmarks: icon = bookmark["icon"] if not icon: icon = "bookmark_list" iconlink(bookmark["title"], bookmark["url"], icon) begin_footnote_links() link( _("Add Bookmark"), "javascript:void(0)", onclick="cmk.sidebar.add_bookmark('%s')" % transactions.get(), ) link(_("Edit"), "bookmark_lists.py") end_footnote_links()
def _render_tree(self, tree): for group, attrs in tree.items(): aggr_group_tree = "/".join(attrs["__path__"]) fetch_url = makeuri_contextless( request, [ ("view_name", "aggr_all"), ("aggr_group_tree", aggr_group_tree), ], filename="view.py", ) if attrs.get("__children__"): with foldable_container( treename="bi_aggregation_group_trees", id_=aggr_group_tree, isopen=False, title=HTML( html.render_a( group, href=fetch_url, target="main", )), icon="foldable_sidebar", ): self._render_tree(attrs["__children__"]) else: html.open_ul() bulletlink(group, fetch_url) html.close_ul()
def _show_topic(treename: str, topic: TopicMenuTopic, show_item_icons: bool) -> None: if not topic.items: return with foldable_container( treename=treename, id_=topic.name, isopen=False, title=topic.title, indent=True, icon="foldable_sidebar", ): for item in topic.items: if show_item_icons: html.open_li(class_=["sidebar"] + (["show_more_mode"] if item.is_show_more else [])) iconlink(item.title, item.url, item.icon or "icon_missing") html.close_li() else: bulletlink( item.title, item.url, onclick="return cmk.sidebar.wato_views_clicked(this)")
def render_tree_folder(tree_id, folder, js_func): subfolders = folder.get(".folders", {}).values() is_leaf = len(subfolders) == 0 # Suppress indentation for non-emtpy root folder if folder[".path"] == "" and is_leaf: html.open_ul() # empty root folder elif folder and folder[".path"] != "": html.open_ul(style="padding-left:0px;") title = HTMLWriter.render_a( "%s (%d)" % (folder["title"], folder[".num_hosts"]), href="#", class_="link", onclick="%s(this, '%s');" % (js_func, folder[".path"]), ) if not is_leaf: with foldable_container( treename=tree_id, id_="/" + folder[".path"], isopen=False, title=HTML(title), icon="foldable_sidebar", padding=6, ): for subfolder in sorted(subfolders, key=lambda x: x["title"].lower()): render_tree_folder(tree_id, subfolder, js_func) else: html.li(title) html.close_ul()
def show(self) -> None: items = self._core_toggles() sites.update_site_states_from_dead_sites() site_status_info: Dict[sites.SiteId, List] = {} try: sites.live().set_prepend_site(True) for row in sites.live().query( "GET status\nColumns: %s" % " ".join([i[0] for i in items]) ): site_id, values = row[0], row[1:] site_status_info[site_id] = values finally: sites.live().set_prepend_site(False) for site_id, site_alias in user_sites.sorted_sites(): container: ContextManager[bool] = ( foldable_container( treename="master_control", id_=site_id, isopen=True, title=site_alias, icon="foldable_sidebar", ) if not site_config.is_single_local_site() else nullcontext(False) ) with container: try: self._show_master_control_site(site_id, site_status_info, items) except Exception as e: logger.exception("error rendering master control for site %s", site_id) write_snapin_exception(e)
def _dump_get_vars( writer: HTMLWriter, request: Request, ) -> None: with foldable_container( treename="html", id_="debug_vars", isopen=True, title=_("GET/POST variables of this page"), ): debug_vars(writer, request, hide_with_mouse=False)
def test_foldable_container(register_builtin_html) -> None: with output_funnel.plugged(): with foldable_container(treename="name", id_="id", isopen=False, title="Title") as is_open: assert is_open is False code = output_funnel.drain() assert compare_html( code, '''<div class="foldable closed"><b onclick="cmk.foldable_container.toggle("name", "id", "")" class="treeangle title">Title</b><img id="treeimg.name.id" onclick="cmk.foldable_container.toggle("name", "id", "")" src="themes/facelift/images/tree_closed.svg" class="treeangle closed" /><br/><ul id="tree.name.id" style="padding-left: 15px; " class="treeangle closed"></ul></div>''')
def _show_tree_nodes(self, maps, children): for map_name, map_cfg in maps.items(): html.open_li() if map_name in children: with foldable_container( treename="nagvis", id_=map_name, isopen=False, title=map_cfg["alias"], title_url=map_cfg["url"], title_target="main", indent=False, icon="foldable_sidebar", ): self._show_tree_nodes(children[map_name], children) else: html.a(map_cfg["alias"], href=map_cfg["url"], target="main", class_="link") html.close_li()
class UserLoginTwoFactor(Page): def page(self) -> None: assert user.id is not None html.set_render_headfoot(False) html.add_body_css_class("login") html.add_body_css_class("two_factor") html.header(_("Two-factor authentication"), Breadcrumb(), javascripts=[]) html.open_div(id_="login") html.open_div(id_="login_window") html.open_a(href="https://checkmk.com") html.img( src=theme.detect_icon_path(icon_name="logo", prefix="mk-"), id_="logo", class_="custom" if theme.has_custom_logo() else None, ) html.close_a() if not is_two_factor_login_enabled(user.id): raise MKGeneralException( _("Two-factor authentication not enabled")) html.begin_form("two_factor_login", method="POST", add_transid=False, action="user_login_two_factor.py") html.prevent_password_auto_completion() html.hidden_field( "_origtarget", origtarget := request.get_url_input("_origtarget", "index.py")) if backup_code := request.get_ascii_input("_backup_code"): if is_two_factor_backup_code_valid(user.id, backup_code): set_two_factor_completed() raise HTTPRedirect(origtarget) html.label( _("Two-factor authentication"), for_="webauthn_message", id_="label_2fa", class_="legend", ) html.div("", id_="webauthn_message") with foldable_container( treename="webauthn_backup_codes", id_="backup_container", isopen=False, title=_("Use backup code"), indent=False, save_state=False, ): html.label( "%s:" % _("Backup code"), id_="label_pass", class_=["legend"], for_="_backup_code", ) html.br() html.password_input("_backup_code", id_="input_pass", size=None) html.open_div(id_="button_text") html.button("_use_backup_code", _("Use backup code"), cssclass="hot") html.close_div() html.close_div() if user_errors: html.open_div(id_="login_error") html.show_user_errors() html.close_div() html.javascript("cmk.webauthn.login()") html.hidden_fields() html.end_form() html.close_div() html.footer()
def _render_tag_tree_level(self, tree_spec, path, cwd, title, tree) -> None: if not self._is_tag_subdir( path=path, cwd=cwd) and not self._is_tag_subdir(path=cwd, cwd=path): return container: ContextManager[bool] = nullcontext(False) if path != cwd and self._is_tag_subdir(path, cwd): bullet = self._tag_tree_bullet(self._tag_tree_worst_state(tree), path, False) if self._tag_tree_has_svc_problems(tree): bullet += html.render_icon_button( self._tag_tree_url(tree_spec, path, "svcproblems"), _("Show the service problems contained in this branch"), "svc_problems", target="main", ) if path: container = foldable_container( treename="tag-tree", id_=".".join(map(str, path)), isopen=False, title=bullet + title, icon="foldable_sidebar", ) with container: for (node_title, node_value), subtree in sorted( tree.get("_children", {}).items()): subpath = path + [node_value or ""] url = self._tag_tree_url(tree_spec, subpath, "allhosts") if "_num_hosts" in subtree: node_title += " (%d)" % subtree["_num_hosts"] node_title = HTMLWriter.render_a(node_title, href=url, target="main") if "_children" not in subtree: if self._is_tag_subdir(path, cwd): html.write_html( self._tag_tree_bullet(subtree.get("_state", 0), subpath, True)) if subtree.get("_svc_problems"): url = self._tag_tree_url(tree_spec, subpath, "svcproblems") html.icon_button( url, _("Show the service problems contained in this branch" ), "svc_problems", target="main", ) html.write_html(node_title) html.br() else: self._render_tag_tree_level(tree_spec, subpath, cwd, node_title, subtree)
def _end(self) -> None: if not self.rows and self.options["omit_if_empty"]: return if self.options["output_format"] == "csv": self._write_csv(csv_separator=request.get_str_input_mandatory( "csv_separator", ";")) return container: ContextManager[bool] = nullcontext(False) if self.title: if self.options["foldable"] in [ Foldable.FOLDABLE_SAVE_STATE, Foldable.FOLDABLE_STATELESS, ]: html.open_div(class_="foldable_wrapper") container = foldable_container( treename="table", id_=self.id, isopen=self.isopen, indent=False, title=HTMLWriter.render_h3(self.title, class_=["treeangle", "title"]), save_state=self.options["foldable"] == Foldable.FOLDABLE_SAVE_STATE, ) else: html.h3(self.title, class_="table") with container: if self.help: html.help(self.help) if not self.rows: html.div(self.empty_text, class_="info") return # Controls whether or not actions are available for a table rows, actions_visible, search_term = self._evaluate_user_opts() # Apply limit after search / sorting etc. num_rows_unlimited = len(rows) limit = self.limit if limit: # only use rows up to the limit plus the fixed rows limited_rows = [] for index in range(num_rows_unlimited): row = rows[index] if index < limit or isinstance(row, GroupHeader) or row.fixed: limited_rows.append(row) # Display corrected number of rows num_rows_unlimited -= len([ r for r in limited_rows if isinstance(row, GroupHeader) or r.fixed ]) rows = limited_rows # Render header if self.limit_hint is not None: num_rows_unlimited = self.limit_hint if limit and num_rows_unlimited > limit: html.show_message( _("This table is limited to show only %d of %d rows. " 'Click <a href="%s">here</a> to disable the limitation.') % (limit, num_rows_unlimited, makeuri(request, [("limit", "none")]))) self._write_table(rows, num_rows_unlimited, self._show_action_row(), actions_visible, search_term) if self.title and self.options["foldable"] in [ Foldable.FOLDABLE_SAVE_STATE, Foldable.FOLDABLE_STATELESS, ]: html.close_div() return
def _show_patterns(self): import cmk.gui.logwatch as logwatch collection = SingleRulesetRecursively("logwatch_rules") collection.load() ruleset = collection.get("logwatch_rules") html.h3(_("Logfile patterns")) if ruleset.is_empty(): html.open_div(class_="info") html.write_text( "There are no logfile patterns defined. You may create " 'logfile patterns using the <a href="%s">Rule Editor</a>.' % folder_preserving_link([ ("mode", "edit_ruleset"), ("varname", "logwatch_rules"), ])) html.close_div() # Loop all rules for this ruleset already_matched = False abs_rulenr = 0 for folder, rulenr, rule in ruleset.get_rules(): # Check if this rule applies to the given host/service if self._hostname: service_desc = self._get_service_description( self._hostname, "logwatch", self._item) # If hostname (and maybe filename) try match it rule_matches = rule.matches_host_and_item( Folder.current(), self._hostname, self._item, service_desc) else: # If no host/file given match all rules rule_matches = True with foldable_container( treename="rule", id_=str(abs_rulenr), isopen=True, title=HTML("<b>Rule #%d</b>" % (abs_rulenr + 1)), indent=False, ), table_element("pattern_editor_rule_%d" % abs_rulenr, sortable=False, css="logwatch") as table: abs_rulenr += 1 # TODO: What's this? pattern_list = rule.value if isinstance(pattern_list, dict): pattern_list = pattern_list["reclassify_patterns"] # Each rule can hold no, one or several patterns. Loop them all here for state, pattern, comment in pattern_list: match_class = "" disp_match_txt = HTML("") match_img = "" if rule_matches: # Applies to the given host/service matched = re.search(pattern, self._match_txt) if matched: # Prepare highlighted search txt match_start = matched.start() match_end = matched.end() disp_match_txt = ( escape_to_html(self._match_txt[:match_start]) + HTMLWriter.render_span( self._match_txt[match_start:match_end], class_="match") + escape_to_html(self._match_txt[match_end:])) if not already_matched: # First match match_class = "match first" match_img = "match" match_title = _( "This logfile pattern matches first and will be used for " "defining the state of the given line.") already_matched = True else: # subsequent match match_class = "match" match_img = "imatch" match_title = _( "This logfile pattern matches but another matched first." ) else: match_img = "nmatch" match_title = _( "This logfile pattern does not match the given string." ) else: # rule does not match match_img = "nmatch" match_title = _("The rule conditions do not match.") table.row() table.cell(_("Match")) html.icon("rule%s" % match_img, match_title) cls = ([ "state%d" % logwatch.level_state(state), "fillbackground" ] if match_class == "match first" else []) table.cell(_("State"), HTMLWriter.render_span( logwatch.level_name(state)), css=cls) table.cell(_("Pattern"), HTMLWriter.render_tt(pattern)) table.cell(_("Comment"), comment) table.cell(_("Matched line"), disp_match_txt) table.row(fixed=True) table.cell(colspan=5) edit_url = folder_preserving_link([ ("mode", "edit_rule"), ("varname", "logwatch_rules"), ("rulenr", rulenr), ("item", mk_repr(self._item).decode()), ("rule_folder", folder.path()), ("rule_id", rule.id), ]) html.icon_button(edit_url, _("Edit this rule"), "edit")