def _render_tag_group_list(self): with table_element( "tags", _("Tag groups"), help= (_("Tags are the basis of Check_MK's rule based configuration. " "If the first step you define arbitrary tag groups. A host " "has assigned exactly one tag out of each group. These tags can " "later be used for defining parameters for hosts and services, " "such as <i>disable notifications for all hosts with the tags " "<b>Network device</b> and <b>Test</b></i>.")), empty_text=_("You haven't defined any tag groups yet."), searchable=False, sortable=False, ) as table: for nr, tag_group in enumerate(self._effective_config.tag_groups): table.row() table.cell(_("Actions"), css=["buttons"]) self._show_tag_icons(tag_group, nr) table.cell(_("ID"), tag_group.id) table.cell(_("Title"), tag_group.title) table.cell(_("Topic"), tag_group.topic or _("Tags")) table.cell(_("Demonstration"), sortable=False) if tag_group.help: html.help(tag_group.help) html.begin_form("tag_%s" % tag_group.id) tag_group_attribute = host_attribute("tag_%s" % tag_group.id) tag_group_attribute.render_input( "", tag_group_attribute.default_value()) html.end_form()
def _table_head( treename: str, id_: str, isopen: bool, title: str, show_more_toggle: bool, help_text: Union[str, HTML, None] = None, ) -> None: onclick = foldable_container_onclick(treename, id_, fetch_url=None) img_id = foldable_container_img_id(treename, id_) html.open_thead() html.open_tr(class_="heading") html.open_td(id_="nform.%s.%s" % (treename, id_), onclick=onclick, colspan=2) html.img( id_=img_id, class_=["treeangle", "nform", "open" if isopen else "closed"], src=theme.url("images/tree_closed.svg"), align="absbottom", ) html.write_text(title) html.help(help_text) if show_more_toggle: html.more_button("foldable_" + id_, dom_levels_up=4, with_text=True) html.close_td() html.close_tr() html.close_thead()
def _add_extra_form_sections(self): forms.section(_("Editable by Users")) html.help(_("It is possible to let users edit their custom attributes.")) html.checkbox( "user_editable", self._attr.get("user_editable", True), label=_("Users can change this attribute in their personal settings"), )
def page(self): html.help( _("On this page you can test the defined logfile patterns against a custom text, " "for example a line from a logfile. Using this dialog it is possible to analyze " "and debug your whole set of logfile patterns.")) self._show_try_form() self._show_patterns()
def page(self) -> None: is_configured = self._is_configured() is_configured_globally = self._varname in self._global_settings default_values = ABCConfigDomain.get_all_default_globals() defvalue = default_values[self._varname] value = self._current_settings.get( self._varname, self._global_settings.get(self._varname, defvalue)) hint = self._config_variable.hint() if hint: html.show_warning(hint) html.begin_form("value_editor", method="POST") title = self._valuespec.title() assert isinstance(title, str) forms.header(title) if not active_config.wato_hide_varnames: forms.section(_("Configuration variable:")) html.tt(self._varname) forms.section(_("Current setting")) self._valuespec.render_input("ve", value) self._valuespec.set_focus("ve") html.help(self._valuespec.help()) if is_configured_globally: self._show_global_setting() forms.section(_("Factory setting")) html.write_text(self._valuespec.value_to_html(defvalue)) forms.section(_("Current state")) if is_configured_globally: html.write_text( _('This variable is configured in <a href="%s">global settings</a>.' ) % ("wato.py?mode=edit_configvar&varname=%s" % self._varname)) elif not is_configured: html.write_text(_("This variable is at factory settings.")) else: curvalue = self._current_settings[self._varname] if is_configured_globally and curvalue == self._global_settings[ self._varname]: html.write_text( _("Site setting and global setting are identical.")) elif curvalue == defvalue: html.write_text( _("Your setting and factory settings are identical.")) else: html.write_text(self._valuespec.value_to_html(curvalue)) forms.end() html.hidden_fields() html.end_form()
def _show_custom_user_attr(user_spec: UserSpec, custom_attr) -> None: for name, attr in custom_attr: if attr.user_editable(): vs = attr.valuespec() forms.section(_u(vs.title())) value = user_spec.get(name, vs.default_value()) if not attr.permission() or user.may(attr.permission()): vs.render_input("ua_" + name, value) html.help(_u(vs.help())) else: html.write_text(vs.value_to_html(value))
def page(self): html.open_div(class_="diag_host") html.open_table() html.open_tr() html.open_td() html.begin_form("diag_host", method="POST") html.prevent_password_auto_completion() forms.header(_("Host Properties")) forms.section(legend=False) # The diagnose page shows both snmp variants at the same time # We need to analyse the preconfigured community and set either the # snmp_community or the snmp_v3_credentials vs_dict = {} for key, value in self._host.attributes().items(): if key == "snmp_community" and isinstance(value, tuple): vs_dict["snmp_v3_credentials"] = value continue vs_dict[key] = value vs_host = self._vs_host() vs_host.render_input("vs_host", vs_dict) html.help(vs_host.help()) forms.end() html.open_div(style="margin-bottom:10px") html.close_div() forms.header(_("Options")) value = {} forms.section(legend=False) vs_rules = self._vs_rules() vs_rules.render_input("vs_rules", value) html.help(vs_rules.help()) forms.end() # When clicking "Save & Test" on the "Edit host" page, this will be set # to immediately execute the tests using the just saved settings if request.has_var("_start_on_load"): html.final_javascript("cmk.page_menu.form_submit('diag_host', '_save');") html.hidden_fields() html.end_form() html.close_td() html.open_td(style="padding-left:10px;") self._show_diagnose_output()
def _show_extra_page_elements(self) -> None: super()._show_extra_page_elements() forms.header(_("Permissions")) forms.section(_("Permitted HW/SW inventory paths")) self._vs_inventory_paths_and_keys().render_input( "inventory_paths", self.group.get("inventory_paths")) if self._get_nagvis_maps(): forms.section(_("Access to NagVis Maps")) html.help(_("Configure access permissions to NagVis maps.")) self._vs_nagvis_maps().render_input( "nagvis_maps", self.group.get("nagvis_maps", []))
def _activation_form(self): if not user.may("wato.activate"): html.show_warning( _("You are not permitted to activate configuration changes.")) return if not self._changes: return if not user.may("wato.activateforeign" ) and self._has_foreign_changes_on_any_site(): html.show_warning( _("Sorry, you are not allowed to activate changes of other users." )) return valuespec = _vs_activation(self.title(), self.has_foreign_changes()) html.begin_form("activate", method="POST", action="") html.hidden_field("activate_until", self._get_last_change_id(), id_="activate_until") if valuespec: title = valuespec.title() assert title is not None forms.header(title) valuespec.render_input("activate", self._value) valuespec.set_focus("activate") html.help(valuespec.help()) if self.has_foreign_changes(): if user.may("wato.activateforeign"): html.show_warning( _("There are some changes made by your colleagues that you will " "activate if you proceed. You need to enable the checkbox above " "to confirm the activation of these changes.")) else: html.show_warning( _("There are some changes made by your colleagues that you can not " "activate because you are not permitted to. You can only activate " "the changes on the sites that are not affected by these changes. " "<br>" "If you need to activate your changes on all sites, please contact " "a permitted user to do it for you.")) forms.end() html.hidden_field("selection_id", weblib.selection_id()) html.hidden_fields() html.end_form() init_rowselect(self.name())
def _show_form(self) -> None: assert user.id is not None users = userdb.load_users() user_spec: Optional[UserSpec] = users.get(user.id) if user_spec is None: html.show_warning(_("Sorry, your user account does not exist.")) html.footer() return html.begin_form("profile", method="POST") html.prevent_password_auto_completion() html.open_div(class_="wato") forms.header(_("Personal settings")) forms.section(_("Username"), simple=True) html.write_text(user_spec.get("user_id", user.id)) forms.section(_("Full name"), simple=True) html.write_text(user_spec.get("alias", "")) select_language(user_spec) # Let the user configure how he wants to be notified rulebased_notifications = rulebased_notifications_enabled() if (not rulebased_notifications and user.may("general.edit_notifications") and user_spec.get("notifications_enabled")): forms.section(_("Notifications")) html.help( _("Here you can configure how you want to be notified about host and service problems and " "other monitoring events.")) get_vs_flexible_notifications().render_input( "notification_method", user_spec.get("notification_method")) if user.may("general.edit_user_attributes"): custom_user_attr_topics = get_user_attributes_by_topic() _show_custom_user_attr(user_spec, custom_user_attr_topics.get("personal", [])) forms.header(_("User interface settings")) _show_custom_user_attr( user_spec, custom_user_attr_topics.get("interface", [])) forms.end() html.close_div() html.hidden_fields() html.end_form() html.footer()
def show_create_view_dialog(next_url=None): vs_ds = DatasourceSelection() ds = "services" # Default selection title = _("Create view") breadcrumb = visuals.visual_page_breadcrumb("views", title, "create") make_header( html, title, breadcrumb, make_simple_form_page_menu( _("View"), breadcrumb, form_name="create_view", button_name="_save", save_title=_("Continue"), ), ) if request.var("_save") and transactions.check_transaction(): try: ds = vs_ds.from_html_vars("ds") vs_ds.validate_value(ds, "ds") if not next_url: next_url = makeuri( request, [("datasource", ds)], filename="create_view_infos.py", ) else: next_url = next_url + "&datasource=%s" % ds raise HTTPRedirect(next_url) except MKUserError as e: html.user_error(e) html.begin_form("create_view") html.hidden_field("mode", "create") forms.header(_("Select Datasource")) forms.section(vs_ds.title()) vs_ds.render_input("ds", ds) html.help(vs_ds.help()) forms.end() html.hidden_fields() html.end_form() html.footer()
def _show_try_form(self): html.begin_form("try") forms.header(_("Try Pattern Match")) forms.section(_("Hostname")) self._vs_host().render_input("host", self._hostname) forms.section(_("Logfile")) html.help(_("Here you need to insert the original file or pathname")) html.text_input("file", size=80) forms.section(_("Text to match")) html.help( _("You can insert some text (e.g. a line of the logfile) to test the patterns defined " "for this logfile. All patterns for this logfile are listed below. Matching patterns " 'will be highlighted after clicking the "Try out" button.')) html.text_input("match", cssclass="match", size=100) forms.end() html.button("_try", _("Try out")) request.del_var("folder") # Never hand over the folder here html.hidden_fields() html.end_form()
def page(self): all_rulesets = AllRulesets() all_rulesets.load() for_host: bool = not self._service # Object type specific detail information if for_host: self._show_host_info() else: self._show_service_info(all_rulesets) last_maingroup = None for groupname in sorted( rulespec_group_registry.get_host_rulespec_group_names( for_host)): maingroup = groupname.split("/")[0] for rulespec in sorted(rulespec_registry.get_by_group(groupname), key=lambda x: x.title or ""): if (rulespec.item_type == "service") == (not self._service): continue # This rule is not for hosts/services # Open form for that group here, if we know that we have at least one rule if last_maingroup != maingroup: last_maingroup = maingroup rulegroup = get_rulegroup(maingroup) forms.header( rulegroup.title, isopen=maingroup == "monconf", narrow=True, css="rulesettings", ) html.help(rulegroup.help) self._output_analysed_ruleset(all_rulesets, rulespec, svc_desc_or_item=self._service, svc_desc=self._service) forms.end()
def page(self): role_list = sorted(userdb_utils.load_roles().items(), key=lambda a: (a[1]["alias"], a[0])) for section in permission_section_registry.get_sorted_sections(): with table_element( section.name, section.title, foldable=Foldable.FOLDABLE_SAVE_STATE, ) as table: permission_list = permission_registry.get_sorted_permissions(section) if not permission_list: table.row() table.cell(_("Permission"), _("No entries"), css=["wide"]) continue for perm in permission_list: table.row() table.cell(_("Permission"), perm.title, css=["wide"]) html.help(perm.description) for role_id, role in role_list: base_on_id = role.get("basedon", role_id) pvalue = role["permissions"].get(perm.name) if pvalue is None: if base_on_id in perm.defaults: icon_name: Optional[str] = "perm_yes_default" else: icon_name = None else: icon_name = "perm_%s" % (pvalue and "yes" or "no") table.cell(role_id, css=["center"]) if icon_name: html.icon(icon_name) html.close_table()
def page(self) -> None: html.begin_form("group", method="POST") forms.header(_("Properties")) forms.section(_("Name"), simple=not self._new, is_required=True) html.help( _("The name of the group is used as an internal key. It cannot be " "changed later. It is also visible in the status GUI.")) if self._new: html.text_input("name") html.set_focus("name") else: html.write_text(self._name) html.set_focus("alias") forms.section(_("Alias"), is_required=True) html.help(_("An alias or description of this group.")) html.text_input("alias", self.group["alias"]) self._show_extra_page_elements() forms.end() html.hidden_fields() html.end_form()
def page(self): html.help( _("This catalog of check plugins gives you a complete listing of all plugins " "that are shipped with your Check_MK installation. It also allows you to " "access the rule sets for configuring the parameters of the checks and to " "manually create services in case you cannot or do not want to rely on the " "automatic service discovery.")) menu = MainMenu() for topic, _has_second_level, title, helptext in _man_page_catalog_topics( ): menu.add_item( MenuItem( mode_or_url=makeuri( request, [("mode", "check_plugin_topic"), ("topic", topic)], ), title=title, icon="plugins_" + topic, permission=None, description=helptext, )) menu.show()
def page(self): html.help( _("The renaming of hosts is a complex operation since a host's name is being " "used as a unique key in various places. It also involves stopping and starting " "of the monitoring core. You cannot rename a host while you have pending changes." )) html.begin_form("rename_host", method="POST") html.add_confirm_on_submit( "rename_host", _("Are you sure you want to rename the host <b>%s</b>? " "This involves a restart of the monitoring core!") % (self._host.name()), ) forms.header(_("Rename host %s") % self._host.name()) forms.section(_("Current name")) html.write_text(self._host.name()) forms.section(_("New name")) html.text_input("newname", "") forms.end() html.set_focus("newname") html.hidden_fields() html.end_form()
def _select_attributes_for_bulk_cleanup(self, hosts): attributes = self._get_attributes_for_bulk_cleanup(hosts) for attr, is_inherited, num_haveit in attributes: # Legend and Help forms.section(attr.title()) if attr.is_mandatory() and not is_inherited: html.write_text( _("This attribute is mandatory and there is no value " "defined in the host list or any parent folder.")) else: label = "clean this attribute on <b>%s</b> hosts" % ( num_haveit == len(hosts) and "all selected" or str(num_haveit)) html.checkbox("_clean_%s" % attr.name(), False, label=label) html.help(attr.help()) forms.end() if not attributes: html.write_text( _("The selected hosts have no explicit attributes"))
def _render_table_option(self, section_title, label, help_text): """Helper method to implement _show_in_table_option.""" forms.section(section_title) html.help(help_text) html.checkbox("show_in_table", self._attr.get("show_in_table", False), label=label)
def _show_start_form(self): html.begin_form("parentscan", method="POST") html.hidden_fields() # Mode of action html.open_p() if not self._complete_folder: num_selected = len(get_hosts_from_checkboxes()) html.write_text(_("You have selected <b>%d</b> hosts for parent scan. ") % num_selected) html.p( _( "The parent scan will try to detect the last gateway " "on layer 3 (IP) before a host. This will be done by " "calling <tt>traceroute</tt>. If a gateway is found by " "that way and its IP address belongs to one of your " "monitored hosts, that host will be used as the hosts " "parent. If no such host exists, an artifical ping-only " "gateway host will be created if you have not disabled " "this feature." ) ) forms.header(_("Settings for Parent Scan")) self._settings = ParentScanSettings( **user.load_file( "parentscan", { "where": "subfolder", "alias": _("Created by parent scan"), "recurse": True, "select": "noexplicit", "timeout": 8, "probes": 2, "ping_probes": 5, "max_ttl": 10, "force_explicit": False, }, ) ) # Selection forms.section(_("Selection")) if self._complete_folder: html.checkbox("recurse", self._settings.recurse, label=_("Include all subfolders")) html.br() html.radiobutton( "select", "noexplicit", self._settings.select == "noexplicit", _("Skip hosts with explicit parent definitions (even if empty)") + "<br>", ) html.radiobutton( "select", "no", self._settings.select == "no", _("Skip hosts hosts with non-empty parents (also if inherited)") + "<br>", ) html.radiobutton( "select", "ignore", self._settings.select == "ignore", _("Scan all hosts") + "<br>" ) # Performance forms.section(_("Performance")) html.open_table() html.open_tr() html.open_td() html.write_text(_("Timeout for responses") + ":") html.close_td() html.open_td() html.text_input("timeout", str(self._settings.timeout), size=2, cssclass="number") html.write_text(_("sec")) html.close_td() html.close_tr() html.open_tr() html.open_td() html.write_text(_("Number of probes per hop") + ":") html.close_td() html.open_td() html.text_input("probes", str(self._settings.probes), size=2, cssclass="number") html.close_td() html.close_tr() html.open_tr() html.open_td() html.write_text(_("Maximum distance (TTL) to gateway") + ":") html.close_td() html.open_td() html.text_input("max_ttl", str(self._settings.max_ttl), size=2, cssclass="number") html.close_td() html.close_tr() html.open_tr() html.open_td() html.write_text(_("Number of PING probes") + ":") html.help( _( "After a gateway has been found, Check_MK checks if it is reachable " "via PING. If not, it is skipped and the next gateway nearer to the " "monitoring core is being tried. You can disable this check by setting " "the number of PING probes to 0." ) ) html.close_td() html.open_td() html.text_input("ping_probes", str(self._settings.ping_probes), size=2, cssclass="number") html.close_td() html.close_tr() html.close_table() # Configuring parent forms.section(_("Configuration")) html.checkbox( "force_explicit", deflt=self._settings.force_explicit, label=_( "Force explicit setting for parents even if setting matches that of the folder" ), ) # Gateway creation forms.section(_("Creation of gateway hosts")) html.write_text(_("Create gateway hosts in")) html.open_ul() html.radiobutton( "where", "subfolder", self._settings.where == "subfolder", _("in the subfolder <b>%s/Parents</b>") % Folder.current_disk_folder().title(), ) html.br() html.radiobutton( "where", "here", self._settings.where == "here", _("directly in the folder <b>%s</b>") % Folder.current_disk_folder().title(), ) html.br() html.radiobutton( "where", "there", self._settings.where == "there", _("in the same folder as the host") ) html.br() html.radiobutton( "where", "nowhere", self._settings.where == "nowhere", _("do not create gateway hosts") ) html.close_ul() html.write_text(_("Alias for created gateway hosts") + ": ") html.text_input("alias", default_value=self._settings.alias) forms.end() # Start button html.button("_start", _("Start")) html.hidden_fields() html.end_form()
def _preview(self) -> None: html.begin_form("preview", method="POST") self._preview_form() attributes = self._attribute_choices() # first line could be missing in situation of import error csv_reader = self._open_csv_file() if not csv_reader: return # don't try to show preview when CSV could not be read html.h2(_("Preview")) attribute_list = "<ul>%s</ul>" % "".join( ["<li>%s (%s)</li>" % a for a in attributes if a[0] is not None] ) html.help( _( "This list shows you the first 10 rows from your CSV file in the way the import is " "currently parsing it. If the lines are not splitted correctly or the title line is " "not shown as title of the table, you may change the import settings above and try " "again." ) + "<br><br>" + _( "The first row below the titles contains fields to specify which column of the " "CSV file should be imported to which attribute of the created hosts. The import " "progress is trying to match the columns to attributes automatically by using the " "titles found in the title row (if you have some). " "If you use the correct titles, the attributes can be mapped automatically. The " "currently available attributes are:" ) + attribute_list + _( "You can change these assignments according to your needs and then start the " "import by clicking on the <i>Import</i> button above." ) ) # Wenn bei einem Host ein Fehler passiert, dann wird die Fehlermeldung zu dem Host angezeigt, so dass man sehen kann, was man anpassen muss. # Die problematischen Zeilen sollen angezeigt werden, so dass man diese als Block in ein neues CSV-File eintragen kann und dann diese Datei # erneut importieren kann. if self._has_title_line: try: headers = list(next(csv_reader)) except StopIteration: headers = [] # nope, there is no header else: headers = [] rows = list(csv_reader) # Determine how many columns should be rendered by using the longest column num_columns = max([len(r) for r in [headers] + rows]) with table_element( sortable=False, searchable=False, omit_headers=not self._has_title_line ) as table: # Render attribute selection fields table.row() for col_num in range(num_columns): header = headers[col_num] if len(headers) > col_num else None table.cell(escape_to_html_permissive(header)) attribute_varname = "attribute_%d" % col_num if request.var(attribute_varname): attribute_method = request.get_ascii_input_mandatory(attribute_varname) else: attribute_method = self._try_detect_default_attribute(attributes, header) request.del_var(attribute_varname) html.dropdown( "attribute_%d" % col_num, attributes, deflt=attribute_method, autocomplete="off" ) # Render sample rows for row in rows: table.row() for cell in row: table.cell(None, cell) html.end_form()
def page(self): search = get_search_expression() html.begin_form("role", method="POST") # ID forms.header(_("Basic properties"), css="wide") forms.section(_("Internal ID"), simple="builtin" in self._role, is_required=True) if self._role.get("builtin"): html.write_text("%s (%s)" % (self._role_id, _("builtin role"))) html.hidden_field("id", self._role_id) else: html.text_input("id", self._role_id) html.set_focus("id") # Alias forms.section(_("Alias")) html.help(_("An alias or description of the role")) html.text_input("alias", self._role.get("alias", ""), size=50) # Based on if not self._role.get("builtin"): forms.section(_("Based on role")) html.help( _( "Each user defined role is based on one of the builtin roles. " "When created it will start with all permissions of that role. When due to a software " "update or installation of an addons new permissions appear, the user role will get or " "not get those new permissions based on the default settings of the builtin role it's " "based on." ) ) role_choices: Choices = [ (i, r["alias"]) for i, r in self._roles.items() if r.get("builtin") ] html.dropdown( "basedon", role_choices, deflt=self._role.get("basedon", "user"), ordered=True ) forms.end() html.h2(_("Permissions")) # Permissions base_role_id = self._role.get("basedon", self._role_id) html.help( _( "When you leave the permissions at "default" then they get their " "settings from the factory defaults (for builtin roles) or from the " "factory default of their base role (for user define roles). Factory defaults " "may change due to software updates. When choosing another base role, all " "permissions that are on default will reflect the new base role." ) ) for section in permission_section_registry.get_sorted_sections(): # Now filter by the optional search term filtered_perms = [] for perm in permission_registry.get_sorted_permissions(section): if search and ( search not in perm.title.lower() and search not in perm.name.lower() ): continue filtered_perms.append(perm) if not filtered_perms: continue forms.header(section.title, isopen=search is not None, css="wide") for perm in filtered_perms: forms.section(perm.title) pvalue = self._role["permissions"].get(perm.name) def_value = base_role_id in perm.defaults choices: Choices = [ ("yes", _("yes")), ("no", _("no")), ("default", _("default (%s)") % (def_value and _("yes") or _("no"))), ] deflt = {True: "yes", False: "no"}.get(pvalue, "default") html.dropdown("perm_" + perm.name, choices, deflt=deflt, style="width: 130px;") html.help(perm.description) forms.end() html.hidden_fields() html.end_form()
def render_input(self, varprefix: str, value: Any) -> None: value = convert_cgroups_from_tuple(value) # If we're just editing a host, then some of the checkboxes will be missing. # This condition is not very clean, but there is no other way to savely determine # the context. is_host = bool(request.var("host")) or request.var("mode") == "newhost" is_search = varprefix == "host_search" # Only show contact groups I'm currently in and contact # groups already listed here. self.load_data() self._vs_contactgroups().render_input(varprefix + self.name(), value["groups"]) html.hr() if is_host: html.checkbox( varprefix + self.name() + "_use", value["use"], label=_("Add these contact groups to the host"), ) elif not is_search: html.checkbox( varprefix + self.name() + "_recurse_perms", value["recurse_perms"], label=_( "Give these groups also <b>permission on all subfolders</b>" ), ) html.hr() html.checkbox( varprefix + self.name() + "_use", value["use"], label= _("Add these groups as <b>contacts</b> to all hosts <b>in this folder</b>" ), ) html.br() html.checkbox( varprefix + self.name() + "_recurse_use", value["recurse_use"], label= _("Add these groups as <b>contacts</b> to all hosts <b>in all subfolders of this folder</b>" ), ) html.hr() html.help( _("With this option contact groups that are added to hosts are always " "being added to services, as well. This only makes a difference if you have " "assigned other contact groups to services via rules in <i>Host & Service Parameters</i>. " "As long as you do not have any such rule a service always inherits all contact groups " "from its host.")) html.checkbox( varprefix + self.name() + "_use_for_services", value.get("use_for_services", False), label=_("Always add host contact groups also to its services") if is_host else _("Always add these groups as <b>contacts</b> to all services <b>in all subfolders of this folder</b>" ), )
def page(self): # TODO: remove subclass specific things specifict things (everything with _type == 'user') html.begin_form("attr") forms.header(_("Properties")) forms.section(_("Name"), simple=not self._new, is_required=True) html.help( _( "The name of the attribute is used as an internal key. It cannot be " "changed later." ) ) if self._new: html.text_input("name", self._attr.get("name", "")) html.set_focus("name") else: html.write_text(self._name) html.set_focus("title") forms.section(_("Title") + "<sup>*</sup>", is_required=True) html.help(_("The title is used to label this attribute.")) html.text_input("title", self._attr.get("title", "")) forms.section(_("Topic")) html.help(_("The attribute is added to this section in the edit dialog.")) html.dropdown("topic", self._topics, deflt=self._attr.get("topic", self._default_topic)) forms.section(_("Help Text") + "<sup>*</sup>") html.help(_("You might want to add some helpful description for the attribute.")) html.text_area("help", self._attr.get("help", "")) forms.section(_("Data type")) html.help(_("The type of information to be stored in this attribute.")) if self._new: html.dropdown("type", custom_attr_types(), deflt=self._attr.get("type", "")) else: html.write_text(dict(custom_attr_types())[self._attr.get("type")]) self._add_extra_form_sections() self._show_in_table_option() forms.section(_("Add to monitoring configuration")) html.help(self._macro_help) html.checkbox( "add_custom_macro", self._attr.get("add_custom_macro", False), label=self._macro_label ) forms.end() html.show_localization_hint() html.hidden_fields() html.end_form()
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