def render_wato(mini): if not active_config.wato_enabled: html.write_text(_("Setup is disabled.")) return False if not user.may("wato.use"): html.write_text(_("You are not allowed to use the setup.")) return False menu = get_wato_menu_items() if mini: for topic in menu: for item in topic.items: html.icon_button( url=item.url, class_=["show_more_mode"] if item.is_show_more else [], title=item.title, icon=item.icon or "wato", target="main", ) else: show_topic_menu(treename="wato", menu=menu, show_item_icons=True) pending_info = get_pending_changes_info() if pending_info: footnotelinks([(pending_info, "wato.py?mode=changelog")]) html.div("", class_="clear") return None
def _show_failed_notifications(self): if not self.parameters()["show_failed_notifications"]: return failed_notifications = notifications.number_of_failed_notifications( after=notifications.acknowledged_time() ) if not failed_notifications: return html.open_div(class_="spacertop") html.open_div(class_="tacticalalert") confirm_url = makeuri_contextless(request, [], filename="clear_failed_notifications.py") html.icon_button(confirm_url, _("Confirm failed notifications"), "delete", target="main") view_url = makeuri_contextless( request, [("view_name", "failed_notifications")], filename="view.py", ) html.a(_("%d failed notifications") % failed_notifications, target="main", href=view_url) html.close_div() html.close_div()
def _show_credentials( cls, webauthn_credentials: dict[str, WebAuthnCredential]) -> None: with table_element(title=None, searchable=False, sortable=False) as table: for credential in webauthn_credentials.values(): table.row() table.cell(_("Actions"), css=["buttons"]) delete_url = make_confirm_link( url=makeactionuri( request, transactions, [("_delete", credential["credential_id"])]), message=_("Do you really want to delete this credential"), ) html.icon_button(delete_url, _("Delete this credential"), "delete") html.icon_button( makeuri_contextless( request, [("_edit", credential["credential_id"])], filename="user_two_factor_edit_credential.py", ), _("Edit this credential"), "edit", ) table.cell(_("Alias"), credential["alias"]) table.cell( _("Registered at"), time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(credential["registered_at"])), )
def _create_status_box( self, site_ids: Collection[livestatus.SiteId], css_class: str, site_status: str, ): html.open_div(class_="spacertop") html.open_div(class_=css_class) message_template = ungettext("%d site is %s.", "%d sites are %s.", len(site_ids)) message = message_template % (len(site_ids), site_status) tooltip_template = ungettext( "Associated hosts, services and events are not included " "in the Tactical Overview. The %s site is %s.", "Associated hosts, services and events are not included " "in the Tactical Overview. The %s sites are %s.", len(site_ids), ) tooltip = tooltip_template % (site_status, ", ".join(site_ids)) if user.may("wato.sites"): url = makeuri_contextless(request, [("mode", "sites")], filename="wato.py") html.icon_button(url, tooltip, "sites", target="main") html.a(message, target="main", href=url) else: html.icon("sites", tooltip) html.write_text(message) html.close_div() html.close_div()
def render_user_message_table(what: str) -> None: html.open_div() with table_element( "user_messages", sortable=False, searchable=False, omit_if_empty=True ) as table: for entry in sorted(message.get_gui_messages(), key=lambda e: e["time"], reverse=True): if what not in entry["methods"]: continue table.row() msg_id = entry["id"] datetime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(entry["time"])) msg = entry["text"].replace("\n", " ") table.cell(_("Actions"), css=["buttons"], sortable=False) onclick = ( "cmk.utils.delete_user_message('%s', this);cmk.utils.reload_whole_page();" % msg_id if what == "gui_hint" else "cmk.utils.delete_user_message('%s', this);" % msg_id ) html.icon_button( "", _("Delete"), "delete", onclick=onclick, ) table.cell(_("Message"), msg) table.cell(_("Date"), datetime) html.close_div()
def page(self) -> None: html.p( _("Here you can add icons, for example to use them in bookmarks or " "in custom actions of views. Allowed are single PNG image files " "with a maximum size of 80x80 px. Custom actions have to be defined " "in the global settings and can be used in the custom icons rules " "of hosts and services.")) html.begin_form("upload_form", method="POST") self._vs_upload().render_input("_upload_icon", None) html.hidden_fields() html.end_form() icons = sorted(self._load_custom_icons().items()) with table_element("icons", _("Custom Icons")) as table: for icon_name, category_name in icons: table.row() table.cell(_("Actions"), css=["buttons"]) delete_url = make_confirm_link( url=make_action_link([("mode", "icons"), ("_delete", icon_name)]), message=_( "Do you really want to delete the icon <b>%s</b>?") % icon_name, ) html.icon_button(delete_url, _("Delete this Icon"), "delete") table.cell(_("Icon"), html.render_icon(icon_name), css=["buttons"]) table.cell(_("Name"), icon_name) table.cell(_("Category"), IconSelector.category_alias(category_name))
def show(self): failed_notifications = notifications.number_of_failed_notifications( after=notifications.acknowledged_time()) if not failed_notifications: return html.open_div(class_="has_failed_notifications") html.open_div(class_="failed_notifications_inner") confirm_url = makeuri_contextless( request, [], filename="clear_failed_notifications.py") html.icon_button(confirm_url, _("Clear failed notifications"), "closetimewarp", target="main") view_url = makeuri_contextless( request, [("view_name", "failed_notifications")], filename="view.py", ) html.a(_("%d failed notifications") % failed_notifications, href=view_url) html.close_div() html.close_div()
def _show_tag_icons(self, tag_group, nr): # Tag groups were made builtin with ~1.4. Previously users could modify # these groups. These users now have the modified tag groups in their # user configuration and should be able to cleanup this using the GUI # for the moment. Make the buttons available to the users. if self._builtin_config.tag_group_exists( tag_group.id) and not self._tag_config.tag_group_exists( tag_group.id): html.i("(%s)" % _("builtin")) return edit_url = folder_preserving_link([("mode", "edit_tag"), ("edit", tag_group.id)]) html.icon_button(edit_url, _("Edit this tag group"), "edit") html.element_dragger_url("tr", base_url=make_action_link([("mode", "tags"), ("_move", nr)])) delete_url = make_confirm_link( url=make_action_link([("mode", "tags"), ("_delete", tag_group.id)]), message=_("Do you really want to delete the tag group '%s'?") % tag_group.id, ) html.icon_button(delete_url, _("Delete this tag group"), "delete")
def page(self) -> None: with table_element(title=self._table_title(), searchable=False, sortable=False) as table: for key_id, key in sorted(self.key_store.load().items()): cert = crypto.load_certificate(crypto.FILETYPE_PEM, key.certificate.encode("ascii")) table.row() table.cell(_("Actions"), css=["buttons"]) if self._may_edit_config(): message = self._delete_confirm_msg() if key.owner != user.id: message += ( _("<br><b>Note</b>: this key has created by user <b>%s</b>") % key.owner ) delete_url = make_confirm_link( url=makeactionuri(request, transactions, [("_delete", key_id)]), message=message, ) html.icon_button(delete_url, _("Delete this key"), "delete") download_url = makeuri_contextless( request, [("mode", self.download_mode), ("key", key_id)], ) html.icon_button(download_url, _("Download this key"), "download") table.cell(_("Description"), key.alias) table.cell(_("Created"), cmk.utils.render.date(key.date)) table.cell(_("By"), key.owner) table.cell(_("Digest (MD5)"), cert.digest("md5").decode("ascii"))
def _show_aux_tag_icons(self, aux_tag: cmk.utils.tags.AuxTag) -> None: if aux_tag.id in self._builtin_config.aux_tag_list.get_tag_ids(): html.i("(%s)" % _("builtin")) return edit_url = folder_preserving_link([("mode", "edit_auxtag"), ("edit", aux_tag.id)]) html.icon_button(edit_url, _("Edit this auxiliary tag"), "edit")
def _show_action_cell(self, table, ident): super()._show_action_cell(table, ident) html.icon_button( self._search_url(ident), _("Show rules using this %s") % self._mode_type.name_singular(), "search", )
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_aux_tag_icons(self, aux_tag: cmk.utils.tags.AuxTag) -> None: if aux_tag.id in self._builtin_config.aux_tag_list.get_tag_ids(): html.i("(%s)" % _("builtin")) return edit_url = folder_preserving_link([("mode", "edit_auxtag"), ("edit", aux_tag.id)]) delete_url = make_confirm_link( url=make_action_link([("mode", "tags"), ("_del_aux", aux_tag.id)]), message=_("Do you really want to delete the auxiliary tag '%s'?") % aux_tag.id, ) html.icon_button(edit_url, _("Edit this auxiliary tag"), "edit") html.icon_button(delete_url, _("Delete this auxiliary tag"), "delete")
def _show_tag_group_icons(self, tag_group: cmk.utils.tags.TagGroup) -> None: # Tag groups were made builtin with ~1.4. Previously users could modify # these groups. These users now have the modified tag groups in their # user configuration and should be able to cleanup this using the GUI # for the moment. Make the buttons available to the users. if self._builtin_config.tag_group_exists( tag_group.id) and not self._tag_config.tag_group_exists( tag_group.id): html.i("(%s)" % _("builtin")) return edit_url = folder_preserving_link([("mode", "edit_tag"), ("edit", tag_group.id)]) html.icon_button(edit_url, _("Edit this tag group"), "edit")
def _assume_icon(self, site, host, service): ass = user.bi_assumptions.get( _get_state_assumption_key(site, host, service)) current_state = str(ass).lower() html.icon_button( url=None, title=_( "Assume another state for this item (reload page to activate)" ), icon="assume_%s" % current_state, onclick="cmk.bi.toggle_assumption(this, '%s', '%s', '%s');" % (site, host, service.replace("\\", "\\\\") if service else ""), cssclass="assumption", )
def page(self): with table_element() as table: for index, connection in enumerate(load_connection_config()): table.row() table.cell(_("Actions"), css=["buttons"]) edit_url = folder_preserving_link([("mode", "edit_ldap_connection"), ("id", connection["id"])]) delete_url = make_confirm_link( url=make_action_link([("mode", "ldap_config"), ("_delete", index)]), message= _("Do you really want to delete the LDAP connection <b>%s</b>?" ) % connection["id"], ) drag_url = make_action_link([("mode", "ldap_config"), ("_move", index)]) clone_url = folder_preserving_link([ ("mode", "edit_ldap_connection"), ("clone", connection["id"]) ]) html.icon_button(edit_url, _("Edit this LDAP connection"), "edit") html.icon_button(clone_url, _("Create a copy of this LDAP connection"), "clone") html.element_dragger_url("tr", base_url=drag_url) html.icon_button(delete_url, _("Delete this LDAP connection"), "delete") table.cell("", css=["narrow"]) if connection.get("disabled"): html.icon( "disabled", _("This connection is currently not being used for synchronization." ), ) else: html.empty_icon_button() table.cell(_("ID"), connection["id"]) if cmk_version.is_managed_edition(): table.cell(_("Customer"), managed.get_customer_name(connection)) table.cell(_("Description")) url = connection.get("docu_url") if url: html.icon_button( url, _("Context information about this connection"), "url", target="_blank") html.write_text(" ") html.write_text(connection["description"])
def _show_link( self, entry: PageMenuEntry, url: Optional[str], onclick: Optional[str], target: Optional[str], ) -> None: classes = ["link", "enabled" if entry.is_enabled else "disabled"] if entry.is_suggested: classes.append("suggested") html.icon_button( url=url, onclick=onclick, title=entry.shortcut_title or entry.title, icon=entry.icon_name, target=target, class_=[" ".join(classes)], id_=("menu_shortcut_%s" % entry.name if entry.name else None), )
def _show_tree_selection(self): html.begin_form("vtree") html.dropdown( "vtree", self._tree_choices(), deflt="%s" % self._current_tree_id, onchange="virtual_host_tree_changed(this)", style="width:210px" if self._current_tree_path else None, ) # Give chance to change one level up, if we are in a subtree if self._current_tree_path: upurl = "javascript:virtual_host_tree_enter('%s')" % "|".join( self._current_tree_path[:-1]) html.icon_button(upurl, _("Go up one tree level"), "back") html.br() html.end_form() html.final_javascript(self._javascript())
def _show_ruleset(self, varname): if varname not in rulespec_registry: return rulespec = rulespec_registry[varname] url = makeuri_contextless(request, [("mode", "edit_ruleset"), ("varname", varname)]) html.open_tr() html.th(_("Parameter rule set")) html.open_td() html.icon_button(url, _("Edit parameter rule set for this check type"), "check_parameters") html.a(rulespec.title, url) html.close_td() html.close_tr() html.open_tr() html.th(_("Example for Parameters")) html.open_td() vs = rulespec.valuespec vs.render_input("dummy", vs.default_value()) html.close_td() html.close_tr()
def page(self): if not self._attrs: html.div(_("No custom attributes are defined yet."), class_="info") return with table_element(self._type + "attrs") as table: for custom_attr in sorted(self._attrs, key=lambda x: x["title"]): table.row() table.cell(_("Actions"), css=["buttons"]) edit_url = folder_preserving_link( [("mode", "edit_%s_attr" % self._type), ("edit", custom_attr["name"])] ) delete_url = make_confirm_link( url=makeactionuri(request, transactions, [("_delete", custom_attr["name"])]), message=_('Do you really want to delete the custom attribute "%s"?') % custom_attr["name"], ) html.icon_button(edit_url, _("Properties"), "edit") html.icon_button(delete_url, _("Delete"), "delete") table.cell(_("Name"), custom_attr["name"]) table.cell(_("Title"), custom_attr["title"]) table.cell(_("Type"), dict(custom_attr_types())[custom_attr["type"]])
def page(self): with table_element("roles") as table: users = userdb.load_users() for rid, role in sorted(self._roles.items(), key=lambda a: (a[1]["alias"], a[0])): table.row() # Actions table.cell(_("Actions"), css=["buttons"]) edit_url = folder_preserving_link([("mode", "edit_role"), ("edit", rid)]) clone_url = make_action_link([("mode", "roles"), ("_clone", rid)]) delete_url = make_confirm_link( url=make_action_link([("mode", "roles"), ("_delete", rid)]), message=_("Do you really want to delete the role %s?") % rid, ) html.icon_button(edit_url, _("Properties"), "edit") html.icon_button(clone_url, _("Clone"), "clone") if not role.get("builtin"): html.icon_button(delete_url, _("Delete this role"), "delete") # ID table.cell(_("Name"), rid) # Alias table.cell(_("Alias"), role["alias"]) # Type table.cell(_("Type"), _("builtin") if role.get("builtin") else _("custom")) # Modifications table.cell( _("Modifications"), HTMLWriter.render_span( str(len(role["permissions"])), title=_("That many permissions do not use the factory defaults."), ), ) # Users table.cell( _("Users"), HTML(", ").join( [ HTMLWriter.render_a( user.get("alias", user_id), folder_preserving_link([("mode", "edit_user"), ("edit", user_id)]), ) for (user_id, user) in users.items() if rid in user["roles"] ] ), )
def _display_page_controls(self, start_time, end_time, previous_log_time, next_log_time): html.open_div(class_="paged_controls") def time_url_args(t): return [ ("options_start_1_day", time.strftime("%d", time.localtime(t))), ("options_start_1_month", time.strftime("%m", time.localtime(t))), ("options_start_1_year", time.strftime("%Y", time.localtime(t))), ("options_start_sel", "1"), ] if next_log_time is not None: html.icon_button( makeactionuri( request, transactions, [ ("options_start_sel", "0"), ], ), _("Most recent events"), "start", ) html.icon_button( makeactionuri(request, transactions, time_url_args(next_log_time)), "%s: %s" % (_("Newer events"), render.date(next_log_time)), "back", ) else: html.empty_icon_button() html.empty_icon_button() if previous_log_time is not None: html.icon_button( makeactionuri(request, transactions, time_url_args(previous_log_time)), "%s: %s" % (_("Older events"), render.date(previous_log_time)), "forth", ) else: html.empty_icon_button() html.close_div()
def _show_row_cells(self, table: Table, name: GroupName, group: GroupSpec) -> None: table.cell(_("Actions"), css=["buttons"]) edit_url = folder_preserving_link([("mode", "edit_%s_group" % self.type_name), ("edit", name)]) delete_url = make_confirm_link( url=makeactionuri(request, transactions, [("_delete", name)]), message=_('Do you really want to delete the %s group "%s"?') % (self.type_name, name), ) clone_url = folder_preserving_link([("mode", "edit_%s_group" % self.type_name), ("clone", name)]) html.icon_button(edit_url, _("Properties"), "edit") html.icon_button(clone_url, _("Create a copy of this group"), "clone") html.icon_button(delete_url, _("Delete"), "delete") table.cell(_("Name"), name) table.cell(_("Alias"), group["alias"])
def _action_buttons(self, name): edit_url = folder_preserving_link([ ("mode", "edit_timeperiod"), ("edit", name), ]) clone_url = folder_preserving_link([ ("mode", "edit_timeperiod"), ("clone", name), ]) delete_url = make_confirm_link( url=make_action_link([ ("mode", "timeperiods"), ("_delete", name), ]), message=_("Do you really want to delete the time period '%s'?") % name, ) html.icon_button(edit_url, _("Properties"), "edit") html.icon_button(clone_url, _("Create a copy"), "clone") html.icon_button(delete_url, _("Delete"), "delete")
def _show_action_cell(self, table: Table, ident: str) -> None: table.cell(_("Actions"), css=["buttons"]) edit_url = makeuri_contextless( request, [ ("mode", self._mode_type.edit_mode_name()), ("ident", ident), ], ) html.icon_button(edit_url, _("Edit this %s") % self._mode_type.name_singular(), "edit") clone_url = makeuri_contextless( request, [ ("mode", self._mode_type.edit_mode_name()), ("clone", ident), ], ) html.icon_button(clone_url, _("Clone this %s") % self._mode_type.name_singular(), "clone") delete_url = make_confirm_link( url=make_action_link([ ("mode", self._mode_type.list_mode_name()), ("_action", "delete"), ("_delete", ident), ]), message=self._delete_confirm_message(), ) html.icon_button(delete_url, _("Delete this %s") % self._mode_type.name_singular(), "delete")
def render(self, row: Row, cell: Cell) -> CellSpec: single_url = "view.py?" + urlencode_vars( [("view_name", "aggr_single"), ("aggr_name", row["aggr_name"])] ) avail_url = single_url + "&mode=availability" bi_map_url = "bi_map.py?" + urlencode_vars( [ ("aggr_name", row["aggr_name"]), ] ) with output_funnel.plugged(): html.icon_button(bi_map_url, _("Visualize this aggregation"), "aggr") html.icon_button(single_url, _("Show only this aggregation"), "showbi") html.icon_button( avail_url, _("Analyse availability of this aggregation"), "availability" ) if row["aggr_effective_state"]["in_downtime"] != 0: html.icon( "derived_downtime", _("A service or host in this aggregation is in downtime.") ) if row["aggr_effective_state"]["acknowledged"]: html.icon( "ack", _( "The critical problems that make this aggregation non-OK have been acknowledged." ), ) if not row["aggr_effective_state"]["in_service_period"]: html.icon( "outof_serviceperiod", _("This aggregation is currently out of its service period."), ) code = HTML(output_funnel.drain()) return "buttons", code
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: HTML = HTMLWriter.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 = 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 = makeactionuri(request, transactions, [("_%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 = HTML( " " ) # 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( makeuri(request, [("_%s_actions" % table_id, state)]), help_txt, img, cssclass="toggle_actions", ) html.span(header_title) html.close_div() else: html.write_text(header_title) else: html.write_text(header_title) html.close_th() html.close_tr()
def render_job_row(cls, job_id, job_status, odd, job_details_back_url=None): html.open_tr(css="data %s0" % odd) # Actions html.open_td(css="job_actions") if job_status.get("may_stop"): html.icon_button( makeactionuri(request, transactions, [(ActionHandler.stop_job_var, job_id)]), _("Stop this job"), "disable_test", ) if job_status.get("may_delete"): html.icon_button( makeactionuri(request, transactions, [(ActionHandler.delete_job_var, job_id)]), _("Delete this job"), "delete", ) html.close_td() # Job ID html.open_td(css="job_id") uri = makeuri_contextless( request, [ ("mode", "background_job_details"), ("back_url", job_details_back_url), ("job_id", job_id), ], filename="wato.py", ) html.a(job_id, href=uri) html.close_td() # Title html.td(job_status.get("title", _("Background Job")), css="job_title") # State html.td( HTMLWriter.render_span(job_status["state"]), css=cls.get_css_for_jobstate(job_status["state"]), ) # Started html.td(cmk.utils.render.date_and_time(job_status["started"]), css="job_started") # Owner html.td(job_status.get("user", _("Unknown user")), css="job_owner") # PID html.td(job_status["pid"] or "", css="job_pid") # Druation html.td(cmk.utils.render.timespan(job_status.get("duration", 0)), css="job_runtime") # Progress info loginfo = job_status.get("loginfo") if loginfo: if job_status.get( "state") == background_job.JobStatusStates.EXCEPTION: html.td(HTML("<br>".join(loginfo["JobException"])), css="job_last_progress") else: progress_text = "" if loginfo["JobProgressUpdate"]: progress_text += "%s" % loginfo["JobProgressUpdate"][-1] html.td(HTML(progress_text), css="job_last_progress") html.td(HTML("<br>".join(loginfo["JobResult"])), css="job_result") else: html.td("", css="job_last_progress") html.td("", css="job_result")
def _activation_status(self): with table_element( "site-status", title=_("Activation status"), searchable=False, sortable=False, css="activation", foldable=Foldable.FOLDABLE_STATELESS, ) as table: for site_id, site in sort_sites(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 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 nr_changes = len(self._changes_of_site(site_id)) # Activation checkbox table.cell("", css=["buttons"]) if can_activate_all and nr_changes: html.checkbox("site_%s" % site_id, need_action, cssclass="site_checkbox") # Iconbuttons table.cell(_("Actions"), css=["buttons"]) if user.may("wato.sites"): edit_url = folder_preserving_link([("mode", "edit_site"), ("site", 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.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" % nr_changes, 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"] == activate_changes.STATE_SUCCESS: html.write_text(_("Activation needed")) else: html.javascript( "cmk.activation.update_site_activation_state(%s);" % json.dumps(last_state)) html.close_div()
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)