def _toggle_page_menu_entry(name: str, state: bool) -> None: html.javascript("cmk.page_menu.enable_menu_entry(%s, %s)" % (json.dumps(name), json.dumps(state)))
def render_dual_area(lower_points, upper_points, color, alpha=1.0): html.javascript('cmk.prediction.render_dual_area(%s, %s, %s, %f);' % (json.dumps(lower_points), json.dumps(upper_points), json.dumps(color), alpha))
def show_job_details(cls, job_id, job_status): """Renders the complete job details in a single table with left headers""" html.open_table(class_=["data", "headerleft", "job_details"]) # Static info for left, right in [ (_("ID"), job_id), (_("Title"), job_status.get("title", "")), (_("Started"), cmk.utils.render.date_and_time(job_status["started"])), (_("Owner"), job_status.get("user", "")), ]: html.open_tr() html.th(left) html.td(right) html.close_tr() # Actions html.open_tr() html.th(_("Actions")) html.open_td() if job_status.get("may_stop"): html.icon_button( html.makeactionuri([(ActionHandler.stop_job_var, job_id)]), _("Stop this job"), "disable_test", ) if job_status.get("may_delete"): html.icon_button( html.makeactionuri([(ActionHandler.delete_job_var, job_id)]), _("Delete this job"), "delete", ) html.close_td() html.close_tr() # Job state html.open_tr() html.th(_("State")) html.td(job_status["state"], css=cls.get_css_for_jobstate(job_status["state"])) html.close_tr() if job_status["state"] == background_job.JobStatusStates.EXCEPTION: html.open_tr() html.th(_("Acknowledged by")) html.td(job_status.get("acknowledged_by", "")) html.close_tr() # Dynamic data loginfo = job_status.get("loginfo") runtime_info = cmk.utils.render.timespan(job_status.get("duration", 0)) if job_status["state"] == background_job.JobStatusStates.RUNNING \ and job_status.get("estimated_duration") is not None: runtime_info += " (%s: %s)" % ( _("estimated duration"), cmk.utils.render.timespan(job_status["estimated_duration"])) for left, right in [ (_("Runtime"), runtime_info), (_("PID"), job_status["pid"] or ""), (_("Result"), "<br>".join(loginfo["JobResult"])), ]: if right is None: continue html.open_tr() html.th(left) html.td(HTML(right)) html.close_tr() # Exceptions exceptions = loginfo["JobException"] if exceptions: html.open_tr() html.th(_("Exceptions")) html.open_td() if exceptions and "logfile_path" in job_status: exceptions.append( _("More information can be found in %s") % job_status["logfile_path"]) html.open_div(class_="log_output", id_="exception_log") html.pre("\n".join(exceptions)) html.close_div() html.close_td() html.close_tr() # Progress Update html.open_tr() html.th(_("Progress Info")) html.open_td() html.open_div(class_="log_output", style="height: 400px;", id_="progress_log") html.pre(HTML("\n").join(loginfo["JobProgressUpdate"])) html.close_div() html.close_td() html.close_tr() html.close_table() html.javascript( "var log = document.getElementById('progress_log'); log.scrollTop = log.scrollHeight;" )
def render_snapin(self, snapin): # type: (UserSidebarSnapin) -> str snapin_class = snapin.snapin_type name = snapin_class.type_name() snapin_instance = snapin_class() html.open_div(id_="snapin_container_%s" % name, class_="snapin") 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 = {} # type: 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) if config.user.may("general.configure_sidebar"): # Icon for mini/maximizing html.div( "", class_="minisnapin", title=_("Toggle this snapin"), onclick="cmk.sidebar.toggle_sidebar_snapin(this, '%s')" % toggle_url) # Button for closing (removing) a snapin html.open_div(class_="closesnapin") close_url = "sidebar_openclose.py?name=%s&state=off" % name html.icon_button( url=None, title=_("Remove this snapin"), icon="closesnapin", onclick="cmk.sidebar.remove_sidebar_snapin(this, '%s')" % close_url) html.close_div() # The heading. A click on the heading mini/maximizes the snapin toggle_actions = {} # type: 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(HTML(snapin_class.title()), class_=["heading"], **toggle_actions) # 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 not url is 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() write_snapin_exception(e) html.close_div() html.close_div() return refresh_url
def show(self): # type: () -> None filename = cmk.utils.paths.omd_root + '/var/dokuwiki/data/pages/sidebar.txt' html.javascript(""" function wiki_search() { var oInput = document.getElementById('wiki_search_field'); top.frames["main"].location.href = "/%s/wiki/doku.php?do=search&id=" + escape(oInput.value); } """ % config.omd_site()) html.open_form(id_="wiki_search", onsubmit="wiki_search();") html.input(id_="wiki_search_field", type_="text", name="wikisearch") html.icon_button("#", _("Search"), "wikisearch", onclick="wiki_search();") html.close_form() html.div('', id_="wiki_side_clear") start_ul = True ul_started = False try: title = None for line in open(filename).readlines(): line = line.strip() if line == "": if ul_started: html.end_foldable_container() start_ul = True ul_started = False elif line.endswith(":"): title = line[:-1] elif line == "----": pass # html.br() elif line.startswith("*"): if start_ul: if title: html.begin_foldable_container("wikisnapin", title, True, title, indent=True) else: html.open_ul() start_ul = False ul_started = True erg = re.findall(r'\[\[(.*)\]\]', line) if len(erg) == 0: continue erg = erg[0].split('|') if len(erg) > 1: link = erg[0] name = erg[1] else: link = erg[0] name = erg[0] if link.startswith("http://") or link.startswith( "https://"): simplelink(name, link, "_blank") else: erg = name.split(':') if len(erg) > 0: name = erg[-1] else: name = erg[0] bulletlink( name, "/%s/wiki/doku.php?id=%s" % (config.omd_site(), link)) else: html.write_text(line) if ul_started: html.close_ul() except IOError: html.write_html( html.render_p( html.render_text( "To get a navigation menu, you have to create a ") + html.render_a("sidebar", href="/%s/wiki/doku.php?id=%s" % (config.omd_site(), _("sidebar")), target="main") + # html.render_text(" in your wiki first.")))
def render_coordinates(v_scala, t_scala): html.javascript('cmk.prediction.render_coordinates(%s, %s);' % (json.dumps(v_scala), json.dumps(t_scala)))
def render_point(t, v, color): html.javascript('cmk.prediction.render_point(%s, %s, %s);' % (json.dumps(t), json.dumps(v), json.dumps(color)))
def _write_table(self, rows, actions_enabled, actions_visible, search_term): headinfo = _("1 row") if len(rows) == 1 else _("%d rows") % len(rows) html.javascript("cmk.utils.update_header_info(%s);" % json.dumps(headinfo)) table_id = self.id num_cols = self._get_num_cols(rows) empty_columns = self._get_empty_columns(rows, num_cols) if self.options["omit_empty_columns"]: num_cols -= len([v for v in empty_columns if v]) html.open_table(class_=["data", "oddeven", self.css]) # If we have no group headers then paint the headers now if self.rows and self.rows[0][2] != "header": self._render_headers( actions_enabled, actions_visible, empty_columns, ) if actions_enabled and actions_visible: html.open_tr(class_=["data", "even0", "actions"]) html.open_td(colspan=num_cols) if not html.in_form(): html.begin_form("%s_actions" % table_id) if self.options["searchable"]: html.open_div(class_="search") html.text_input("_%s_search" % table_id) html.button("_%s_submit" % table_id, _("Search")) html.button("_%s_reset" % table_id, _("Reset search")) html.set_focus("_%s_search" % table_id) html.close_div() if html.request.has_var('_%s_sort' % table_id): html.open_div(class_=["sort"]) html.button("_%s_reset_sorting" % table_id, _("Reset sorting")) html.close_div() if not html.in_form(): html.begin_form("%s_actions" % table_id) html.hidden_fields() html.end_form() html.close_tr() for nr, (row_spec, css, state, _fixed, attrs) in enumerate(rows): if not css and "class_" in attrs: css = attrs.pop("class_") if not css and "class" in attrs: css = attrs.pop("class") # Intermediate header if state == "header": # Show the header only, if at least one (non-header) row follows if nr < len(rows) - 1 and rows[nr + 1][2] != "header": html.open_tr(class_="groupheader") html.open_td(colspan=num_cols) html.open_h3() html.write(row_spec) html.close_h3() html.close_td() html.close_tr() self._render_headers(actions_enabled, actions_visible, empty_columns) continue oddeven_name = "even" if (nr - 1) % 2 == 0 else "odd" html.open_tr(class_=[ "data", "%s%d" % (oddeven_name, state), css if css else None ], **attrs) for col_index, (cell_content, css_classes, colspan) in enumerate(row_spec): if self.options["omit_empty_columns"] and empty_columns[ col_index]: continue html.open_td(class_=css_classes if css_classes else None, colspan=colspan if colspan else None) html.write(cell_content) html.close_td() html.close_tr() if not rows and search_term: html.open_tr(class_=["data", "odd0", "no_match"]) html.td( _('Found no matching rows. Please try another search term.'), colspan=num_cols) html.close_tr() html.close_table()
def _activation_status(self): with table_element("site-status", searchable=False, sortable=False, css="activation") as table: for site_id, site in sort_sites(cmk.gui.watolib.changes.activation_sites()): table.row() site_status, status = self._get_site_status(site_id, site) is_online = self._site_is_online(status) is_logged_in = self._site_is_logged_in(site_id, site) has_foreign = self._site_has_foreign_changes(site_id) can_activate_all = not has_foreign or config.user.may("wato.activateforeign") # Disable actions for offline sites and not logged in sites if not is_online or not is_logged_in: can_activate_all = False need_restart = self._is_activate_needed(site_id) need_sync = self.is_sync_needed(site_id) need_action = need_restart or need_sync # Activation checkbox table.cell("", css="buttons") if can_activate_all: html.checkbox("site_%s" % site_id, cssclass="site_checkbox") # Iconbuttons table.cell(_("Actions"), css="buttons") if config.user.may("wato.sites"): edit_url = watolib.folder_preserving_link([("mode", "edit_site"), ("edit", site_id)]) html.icon_button(edit_url, _("Edit the properties of this site"), "edit") # State if can_activate_all and need_sync: html.icon_button( url="javascript:void(0)", id_="activate_%s" % site_id, cssclass="activate_site", title=_("This site is not update and needs a replication. Start it now."), icon="need_replicate", onclick="cmk.activation.activate_changes(\"site\", \"%s\")" % site_id) if can_activate_all and need_restart: html.icon_button( url="javascript:void(0)", id_="activate_%s" % site_id, cssclass="activate_site", title=_( "This site needs a restart for activating the changes. Start it now."), icon="need_restart", onclick="cmk.activation.activate_changes(\"site\", \"%s\")" % site_id) if can_activate_all and not need_action: html.icon("siteuptodate", _("This site is up-to-date.")) site_url = site.get("multisiteurl") if site_url: html.icon_button(site_url, _("Open this site's local web user interface"), "url", target="_blank") table.text_cell(_("Site"), site.get("alias", site_id), css="narrow nobr") # Livestatus table.cell(_("Status"), css="narrow nobr") html.status_label(content=status, status=status, title=_("This site is %s") % status) # Livestatus-/Checkmk-Version table.cell(_("Version"), site_status.get("livestatus_version", ""), css="narrow nobr") table.cell(_("Changes"), "%d" % len(self._changes_of_site(site_id)), css="number narrow nobr") table.cell(_("Progress"), css="repprogress") html.open_div(id_="site_%s_status" % site_id, class_=["msg"]) html.close_div() html.open_div(id_="site_%s_progress" % site_id, class_=["progress"]) html.close_div() table.cell(_("Details"), css="details") html.open_div(id_="site_%s_details" % site_id) last_state = self._last_activation_state(site_id) if not is_logged_in: html.write_text(_("Is not logged in.") + " ") if not last_state: html.write_text(_("Has never been activated")) elif (need_action and last_state["_state"] == cmk.gui.watolib.activate_changes.STATE_SUCCESS): html.write_text(_("Activation needed")) else: if html.request.has_var("_finished"): label = _("State") else: label = _("Last state") html.write_text("%s: %s. " % (label, last_state["_status_text"])) if last_state["_status_details"]: html.write(last_state["_status_details"]) html.javascript("cmk.activation.update_site_activation_state(%s);" % json.dumps(last_state)) html.close_div()
def _handle_report_form(self, crash_info: CrashInfo) -> ReportSubmitDetails: details: ReportSubmitDetails try: vs = self._vs_crash_report() details = vs.from_html_vars("_report") vs.validate_value(details, "_report") # Make the resulting page execute the crash report post request url_encoded_params = urlencode_vars([ ("name", details["name"]), ("mail", details["mail"]), ( "crashdump", base64.b64encode( _pack_crash_report( self._get_serialized_crash_report())).decode( "ascii"), ), ]) html.open_div(id_="pending_msg", style="display:none") html.show_message(_("Submitting crash report...")) html.close_div() html.open_div(id_="success_msg", style="display:none") html.show_message( _("Your crash report has been submitted (ID: ###ID###). Thanks for your participation, " "it is very important for the quality of Checkmk.<br><br>" "Please note:" "<ul>" "<li>In general we do <i>not</i> respond to crash reports, " "except we need further information from you.</li>" "<li>We read every feedback thoroughly, but this might happen " "not before a couple of weeks or even months have passed and is " "often aligned with our release cycle.</li>" "<li>If you are in need of a quick solution for your problem, then " "we can help you within the scope of professional support. If you " "already have a support contract, then please use your personal " "support email address to send us a mail refering to your crash " "report.<br>If you are interested in the details about support, " 'you find details on <a href="https://checkmk.com/' 'checkmk_support_contract.html" target="_blank">our website</a>.' )) html.close_div() html.open_div(id_="fail_msg", style="display:none") report_url = makeuri_contextless( request, [ ("subject", "Checkmk Crash Report - " + self._get_version()), ], filename="mailto:" + self._get_crash_report_target(), ) html.show_error( _("Failed to send the crash report. Please download it manually and send it " 'to <a href="%s">%s</a>') % (report_url, self._get_crash_report_target())) html.close_div() html.javascript( "cmk.transfer.submit_crash_report(%s, %s);" % (json.dumps( config.crash_report_url), json.dumps(url_encoded_params))) except MKUserError as e: user_errors.add(e) return details
def show_topology_content(self, hostnames, mode, growth_auto_max_nodes=None, max_nodes=400, mesh_depth=0): div_id = "node_visualization" html.div("", id=div_id) # Filters html.open_div(id="topology_filters") _view, filters = self._get_topology_view_and_filters() html.request.set_var("topology_mesh_depth", str(mesh_depth)) html.request.set_var("topology_max_nodes", str(max_nodes)) cmk.gui.views.show_filter_form(is_open=True, filters=filters) html.close_div() html.javascript( "topology_instance = new cmk.node_visualization.TopologyVisualization(%s, %s);" % (json.dumps(div_id), json.dumps(mode))) if growth_auto_max_nodes: html.javascript("topology_instance.set_growth_auto_max_nodes(%d)" % growth_auto_max_nodes) html.javascript("topology_instance.set_max_nodes(%d)" % max_nodes) html.javascript("topology_instance.set_mesh_depth(%d)" % mesh_depth) html.javascript("topology_instance.set_theme(%s)" % json.dumps(html.get_theme())) overlay_config = self._get_overlay_config() if overlay_config: html.javascript( "topology_instance.set_initial_overlays_config(%s)" % json.dumps(overlay_config)) html.javascript("topology_instance.show_topology(%s)" % json.dumps(hostnames))
def update(self): self.show() html.javascript(self._adjust_font_size_js())
def _show_login_page(self): # type: () -> None html.set_render_headfoot(False) html.add_body_css_class("login") html.header(config.get_page_heading(), javascripts=[]) default_origtarget = "index.py" if html.myfile in [ "login", "logout" ] else html.makeuri([]) origtarget = html.get_url_input("_origtarget", default_origtarget) # Never allow the login page to be opened in the iframe. Redirect top page to login page. # This will result in a full screen login page. html.javascript('''if(top != self) { window.top.location.href = location; }''') # When someone calls the login page directly and is already authed redirect to main page if html.myfile == 'login' and _check_auth(html.request): raise HTTPRedirect(origtarget) html.open_div(id_="login") html.open_div(id_="login_window") html.div("" if "hide_version" in config.login_screen else cmk_version.__version__, id_="version") html.begin_form("login", method='POST', add_transid=False, action='login.py') html.hidden_field('_login', '1') html.hidden_field('_origtarget', origtarget) html.label("%s:" % _('Username'), id_="label_user", class_=["legend"], for_="_username") html.br() html.text_input("_username", id_="input_user") html.label("%s:" % _('Password'), id_="label_pass", class_=["legend"], for_="_password") html.br() html.password_input("_password", id_="input_pass", size=None) if html.has_user_errors(): html.open_div(id_="login_error") html.show_user_errors() html.close_div() html.open_div(id_="button_text") html.button("_login", _('Login')) html.close_div() html.close_div() html.open_div(id_="foot") if config.login_screen.get("login_message"): html.open_div(id_="login_message") html.show_message(config.login_screen["login_message"]) html.close_div() footer = [] # type: List[Union[HTML, str]] for title, url, target in config.login_screen.get("footer_links", []): footer.append(html.render_a(title, href=url, target=target)) if "hide_version" not in config.login_screen: footer.append("Version: %s" % cmk_version.__version__) footer.append("© %s" % html.render_a( "tribe29 GmbH", href="https://checkmk.com", target="_blank")) html.write(HTML(" - ").join(footer)) if cmk_version.is_raw_edition(): html.br() html.br() html.write( _('You can use, modify and distribute Check_MK under the terms of the <a href="%s" target="_blank">' 'GNU GPL Version 2</a>.') % "https://checkmk.com/gpl.html") html.close_div() html.set_focus('_username') html.hidden_fields() html.end_form() html.close_div() html.footer()
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 = 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 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 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 = 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 element"), 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 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=_("Open/close this element"), 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 toggle_page_menu_entries(css_class: str, state: bool) -> None: html.javascript("cmk.page_menu.enable_menu_entries(%s, %s)" % (json.dumps(css_class), json.dumps(state)))
def _show_hosts(self): if not self._folder.has_hosts(): return show_checkboxes = html.request.var('show_checkboxes', '0') == '1' hostnames = sorted(self._folder.hosts().keys(), key=utils.key_num_split) search_text = html.request.var("search") # Helper function for showing bulk actions. This is needed at the bottom # of the table of hosts and - if there are more than just a few - also # at the top of the table. search_shown = False # Show table of hosts in this folder html.begin_form("hosts", method="POST") with table_element("hosts", title=_("Hosts"), searchable=False, omit_empty_columns=True) as table: # Remember if that host has a target folder (i.e. was imported with # a folder information but not yet moved to that folder). If at least # one host has a target folder, then we show an additional bulk action. at_least_one_imported = False more_than_ten_items = False for num, hostname in enumerate(hostnames): if search_text and (search_text.lower() not in hostname.lower()): continue host = self._folder.host(hostname) effective = host.effective_attributes() if effective.get("imported_folder"): at_least_one_imported = True if num == 11: more_than_ten_items = True # Compute colspan for bulk actions colspan = 6 for attr in host_attribute_registry.attributes(): if attr.show_in_table(): colspan += 1 if not self._folder.locked_hosts() and config.user.may( "wato.edit_hosts") and config.user.may("wato.move_hosts"): colspan += 1 if show_checkboxes: colspan += 1 if self._folder.is_search_folder(): colspan += 1 # Add the bulk action buttons also to the top of the table when this # list shows more than 10 rows if more_than_ten_items and \ (config.user.may("wato.edit_hosts") or config.user.may("wato.manage_hosts")): self._bulk_actions(table, at_least_one_imported, True, True, colspan, show_checkboxes) search_shown = True contact_group_names = load_contact_group_information() host_errors = self._folder.host_validation_errors() rendered_hosts = [] # type: List[HostName] # Now loop again over all hosts and display them for hostname in hostnames: self._show_host_row(rendered_hosts, table, hostname, search_text, show_checkboxes, colspan, host_errors, contact_group_names) if config.user.may("wato.edit_hosts") or config.user.may("wato.manage_hosts"): self._bulk_actions(table, at_least_one_imported, False, not search_shown, colspan, show_checkboxes) html.hidden_fields() html.end_form() selected = config.user.get_rowselection(weblib.selection_id(), 'wato-folder-/' + self._folder.path()) row_count = len(rendered_hosts) headinfo = "%d %s" % (row_count, _("host") if row_count == 1 else _("hosts")) html.javascript("cmk.utils.update_header_info(%s);" % json.dumps(headinfo)) if show_checkboxes: selection_properties = { "page_id": "wato-folder-%s" % ('/' + self._folder.path()), "selection_id": weblib.selection_id(), "selected_rows": selected, } html.javascript('cmk.selection.init_rowselect(%s);' % (json.dumps(selection_properties)))
def update(self): self._show_view_as_dashlet(self._dashlet_spec) html.javascript( "cmk.utils.add_simplebar_scrollbar(\"dashlet_content_wrapper\");")
def show(self): html.div(_("Loading maps..."), class_="loading") html.javascript("cmk.sidebar.fetch_nagvis_snapin_contents()")
def render_curve(points, color, width=1, square=False): html.javascript( 'cmk.prediction.render_curve(%s, %s, %d, %d);' % (json.dumps(points), json.dumps(color), width, square and 1 or 0))
def show_topology_content(self, hostnames: List[HostName], mode: str, growth_auto_max_nodes: Optional[int] = None, max_nodes: int = 400, mesh_depth: int = 0) -> None: div_id = "node_visualization" html.div("", id_=div_id) html.javascript( "topology_instance = new cmk.node_visualization.TopologyVisualization(%s, %s);" % (json.dumps(div_id), json.dumps(mode))) if growth_auto_max_nodes: html.javascript("topology_instance.set_growth_auto_max_nodes(%d)" % growth_auto_max_nodes) html.javascript("topology_instance.set_max_nodes(%d)" % max_nodes) html.javascript("topology_instance.set_mesh_depth(%d)" % mesh_depth) html.javascript("topology_instance.set_theme(%s)" % json.dumps(html.get_theme())) overlay_config = self._get_overlay_config() if overlay_config: html.javascript( "topology_instance.set_initial_overlays_config(%s)" % json.dumps(overlay_config)) html.javascript("topology_instance.show_topology(%s)" % json.dumps(hostnames))
def render_area_reverse(points, color, alpha=1.0): html.javascript('cmk.prediction.render_area_reverse(%s, %s, %f);' % (json.dumps(points), json.dumps(color), alpha))
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()