示例#1
0
def jqm_page_navfooter(items: NavigationBar, current: str, page_id: str) -> None:
    html.close_div()  # close content
    html.open_div(
        **{
            "data-role": "footer",
            "data-position": "fixed",
            "data-tap-toggle": "false",
            "data-hide-during-focus": "",
        }
    )
    html.open_div(**{"data-role": "navbar"})
    html.open_ul()

    for href, title, icon, custom_css in items:
        href = makeuri(request, [("page", href), ("search", "Search")])
        if current == href:
            custom_css += " ui-state-persist ui-btn-active"
        else:
            html.open_li()
            html.a(
                title,
                href=href,
                class_=custom_css,
                **{
                    "data-transition": "slide",
                    "data-icon": icon,
                    "data-iconpos": "bottom",
                },
            )
            html.close_li()
    html.close_ul()
    html.close_div()
    html.close_div()
    html.close_div()  # close page-div
    def _show_entry_cells(self, table, ident, entry):
        table.cell(_("Title"), entry["title"])

        table.cell(_("Conditions"))
        html.open_ul(class_="conditions")
        html.open_li()
        html.write_text(
            "%s: %s" %
            (_("Folder"), Folder.folder(
                entry["conditions"]["host_folder"]).alias_path()))
        html.close_li()
        html.close_ul()
        html.write_text(vs_conditions().value_to_html(entry["conditions"]))

        table.cell(_("Editable by"))
        if entry["owned_by"] is None:
            html.write_text(
                _("Administrators (having the permission "
                  '"Write access to all predefined conditions")'))
        else:
            html.write_text(self._contact_group_alias(entry["owned_by"]))

        table.cell(_("Shared with"))
        if not entry["shared_with"]:
            html.write_text(_("Not shared"))
        else:
            html.write_text(", ".join(
                [self._contact_group_alias(g) for g in entry["shared_with"]]))
示例#3
0
 def show(self) -> None:
     html.open_ul()
     for _ident, group in bi.aggregation_group_choices():
         bulletlink(
             group, "view.py?view_name=aggr_group&aggr_group=%s" %
             urlencode(group))
     html.close_ul()
示例#4
0
 def show(self):
     group_type = self._group_type_ident()
     html.open_ul()
     for name, alias in sites.all_groups(group_type.replace("group", "")):
         url = "view.py?view_name=%s&%s=%s" % (group_type, group_type, urlencode(name))
         bulletlink(alias or name, url)
     html.close_ul()
示例#5
0
    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(
                            HTMLWriter.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()
示例#6
0
文件: wato.py 项目: LinuxHaus/checkmk
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()
示例#7
0
def _show_filter_form(show_filters: List[Filter], context: VisualContext) -> None:
    # Sort filters
    s = sorted([(f.sort_index, f.title, f) for f in show_filters if f.available()])

    html.begin_form("filter")
    html.open_ul(**{"data-role": "listview", "data-inset": "false"})
    for _sort_index, title, f in s:
        html.open_li(**{"data-role": "fieldcontain"})
        html.legend(title)
        f.display(context.get(f.ident, {}))
        html.close_li()
    html.close_ul()
    html.hidden_fields()
    html.hidden_field("search", "Search")
    html.hidden_field("page", "data")
    html.form_has_submit_button = True  # a.results_button functions as a submit button
    html.end_form()
    html.final_javascript(
        """
        const filter_form = document.getElementById("form_filter");
        const results_button = document.getElementsByClassName("results_button")[0];

        cmk.forms.enable_select2_dropdowns(filter_form);
        results_button.onclick = function(event) {
            event.preventDefault();
            filter_form.submit();
        };
        """
    )
示例#8
0
文件: tags.py 项目: LinuxHaus/checkmk
def _show_affected_folders(affected_folders: List[CREFolder]) -> None:
    html.open_ul()
    for folder in affected_folders:
        html.open_li()
        html.a(folder.alias_path(), href=folder.edit_url())
        html.close_li()
    html.close_ul()
示例#9
0
文件: tags.py 项目: LinuxHaus/checkmk
def _show_affected_rulesets(affected_rulesets: List[Ruleset]) -> None:
    html.open_ul()
    for ruleset in affected_rulesets:
        html.open_li()
        html.a(
            ruleset.title(),
            href=folder_preserving_link([("mode", "edit_ruleset"),
                                         ("varname", ruleset.name)]),
        )
        html.close_li()
    html.close_ul()
示例#10
0
    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()
示例#11
0
def page_index() -> None:
    title = _("Checkmk Mobile")
    mobile_html_head(title)
    jqm_page_header(
        title,
        right_button=("javascript:document.location.reload();", _("Reload"), "refresh"),
        id_="data",
    )
    items = []
    for view_name, view_spec in views.get_permitted_views().items():
        if view_spec.get("mobile") and not view_spec.get("hidden"):

            datasource = data_source_registry[view_spec["datasource"]]()
            context = visuals.active_context_from_request(datasource.infos, view_spec["context"])

            view = views.View(view_name, view_spec, context)
            view.row_limit = views.get_limit()
            view.only_sites = visuals.get_only_sites_from_context(context)
            view.user_sorters = views.get_user_sorters()
            view.want_checkboxes = views.get_want_checkboxes()

            url = "mobile_view.py?view_name=%s" % view_name
            count = ""
            if not view_spec.get("mustsearch"):
                painter_options = PainterOptions.get_instance()
                painter_options.load(view_name)
                count = '<span class="ui-li-count">%d</span>' % views.get_row_count(view)

            topic = PagetypeTopics.get_topic(view_spec.get("topic", ""))
            items.append((topic.title(), url, "%s %s" % (view_spec["title"], count)))

    jqm_page_index(_("Checkmk Mobile"), items)
    # Link to non-mobile GUI

    html.hr()
    html.open_ul(**{"data-role": "listview", "data-theme": "b", "data-inset": "true"})
    html.open_li()
    html.a(
        _("Classical web GUI"),
        href="index.py?mobile=",
        **{"data-ajax": "false", "data-transition": "fade"},
    )
    html.close_li()
    html.close_ul()

    html.open_ul(**{"data-role": "listview", "data-theme": "f", "data-inset": "true"})
    html.open_li()
    html.a(_("Logout"), href="logout.py", **{"data-ajax": "false", "data-transition": "fade"})
    html.close_li()
    html.close_ul()
    mobile_html_foot()
示例#12
0
文件: tags.py 项目: LinuxHaus/checkmk
def _show_affected_hosts(affected_hosts: List[CREHost]) -> None:
    html.open_ul()
    html.open_li()
    for nr, host in enumerate(affected_hosts):
        if nr > 20:
            html.write_text(_("... (%d more)") % (len(affected_hosts) - 20))
            break

        if nr > 0:
            html.write_text(", ")

        html.a(host.name(), href=host.edit_url())
    html.close_li()
    html.close_ul()
示例#13
0
 def _show_items(self, topic_id: str, topic: TopicMenuTopic) -> None:
     html.open_ul()
     for item in sorted(topic.items, key=lambda g: g.sort_index):
         self._show_item(item)
     html.open_li(class_="show_all_items")
     html.open_a(href="",
                 onclick="cmk.popup_menu.mega_menu_show_all_items('%s')" %
                 topic_id)
     if user.get_attribute("icons_per_item"):
         html.icon("trans")
     html.write_text(_("Show all"))
     html.close_a()
     html.close_li()
     html.close_ul()
示例#14
0
def jqm_page_index_topic_renderer(topic: str, items: Items) -> None:
    has_items_for_topic = any(i for i in items if i[0] == topic)
    if not has_items_for_topic:
        return

    html.p(topic)
    html.open_ul(**{"data-role": "listview", "data-inset": "true"})
    for top, href, title in items:
        if top == topic:
            html.open_li()
            html.open_a(href=href, **{"data-ajax": "false", "data-transition": "flip"})
            html.write_html(HTML(title))
            html.close_a()
            html.close_li()
    html.close_ul()
示例#15
0
def render_werk_description(werk) -> HTML:
    with output_funnel.plugged():
        html.open_p()
        in_list = False
        in_code = False
        for line in werk["body"]:
            if line.startswith("LI:"):
                if not in_list:
                    html.open_ul()
                    in_list = True
                html.li(line[3:])
            else:
                if in_list:
                    html.close_ul()
                    in_list = False

                if line.startswith("H2:"):
                    html.h3(line[3:])
                elif line.startswith("C+:"):
                    html.open_pre(class_="code")
                    in_code = True
                elif line.startswith("F+:"):
                    file_name = line[3:]
                    if file_name:
                        html.div(file_name, class_="filename")
                    html.open_pre(class_="file")
                    in_code = True
                elif line.startswith("C-:") or line.startswith("F-:"):
                    html.close_pre()
                    in_code = False
                elif line.startswith("OM:"):
                    html.write_text("OMD[mysite]:~$ ")
                    html.b(line[3:])
                elif line.startswith("RP:"):
                    html.write_text("root@myhost:~# ")
                    html.b(line[3:])
                elif not line.strip() and not in_code:
                    html.p("")
                else:
                    html.write_text(line + "\n")

        if in_list:
            html.close_ul()

        html.close_p()
        return HTML(output_funnel.drain())
示例#16
0
文件: tags.py 项目: LinuxHaus/checkmk
def _show_aux_tag_used_by_tags(tags: Set[cmk.utils.tags.GroupedTag]) -> None:
    if not tags:
        return

    html.open_ul()
    html.open_li()
    builtin_config = cmk.utils.tags.BuiltinTagConfig()
    for index, tag in enumerate(sorted(tags, key=lambda t: t.choice_title)):
        if index > 0:
            html.write_text(", ")

        # Builtin tag groups can not be edited
        if builtin_config.tag_group_exists(tag.group.id):
            html.write_text(_u(tag.choice_title))
        else:
            edit_url = folder_preserving_link([("mode", "edit_tag"),
                                               ("edit", tag.group.id)])
            html.a(_u(tag.choice_title), href=edit_url)
    html.close_li()
    html.close_ul()
示例#17
0
def render_mobile_list(rows, view, group_cells, cells, num_columns,
                       show_checkboxes):
    if not is_mobile(request, response):
        html.show_error(_("This view can only be used in mobile mode."))
        return

    # Force relative timestamp always. This saves space.
    painter_options = PainterOptions.get_instance()
    painter_options.set("ts_format", "rel")

    html.open_ul(class_="mobilelist", **{"data-role": "listview"})

    # Paint data rows
    for row in rows:
        html.open_li()
        rendered_cells = [cell.render(row) for cell in cells]
        if rendered_cells:  # First cell (assumedly state) is left
            rendered_class, rendered_content = rendered_cells[0]
            html.p(rendered_content,
                   class_=["ui-li-aside", "ui-li-desc", rendered_class])

            if len(rendered_cells) > 1:
                content = HTML(" &middot; ").join([
                    rendered_cell[1]
                    for rendered_cell in rendered_cells[1:num_columns + 1]
                ])
                html.h3(content)

                for rendered_cell, cell in zip(
                        rendered_cells[num_columns + 1:],
                        cells[num_columns + 1:]):
                    rendered_class, rendered_content = rendered_cell
                    html.open_p(class_="ui-li-desc")
                    cell.paint_as_header()
                    html.write_text(": ")
                    html.span(rendered_content, class_=rendered_class)
                    html.close_p()

        html.close_li()
    html.close_ul()
    html.javascript('$("ul.mobilelist a").attr("data-ajax", "false");')
示例#18
0
    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()
示例#19
0
 def _show_tree(self, api_request):
     html.open_ul()
     self._show_tree_nodes(api_request["maps"]["maps"], api_request["maps"]["childs"])
     html.close_ul()
示例#20
0
文件: tags.py 项目: LinuxHaus/checkmk
def _rename_tags_after_confirmation(
        breadcrumb: Breadcrumb, operation: ABCOperation) -> Union[bool, str]:
    """Handle renaming and deletion of tags

    Find affected hosts, folders and rules. Remove or fix those rules according
    the users' wishes.

    Returns:
        True: Proceed, no "question" dialog shown
        False: "Question dialog" shown
        str: Action done after "question" dialog
    """
    repair_mode = request.var("_repair")
    if repair_mode is not None:
        try:
            mode = TagCleanupMode(repair_mode)
        except ValueError:
            raise MKUserError("_repair", "Invalid mode")

        if mode == TagCleanupMode.ABORT:
            raise MKUserError("id_0", _("Aborting change."))

        # make attribute unknown to system, important for save() operations
        if isinstance(operation, OperationRemoveTagGroup):
            undeclare_host_tag_attribute(operation.tag_group_id)

        affected_folders, affected_hosts, affected_rulesets = change_host_tags_in_folders(
            operation, mode, Folder.root_folder())

        return _(
            "Modified folders: %d, modified hosts: %d, modified rulesets: %d"
        ) % (
            len(affected_folders),
            len(affected_hosts),
            len(affected_rulesets),
        )

    message = HTML()
    affected_folders, affected_hosts, affected_rulesets = change_host_tags_in_folders(
        operation, TagCleanupMode.CHECK, Folder.root_folder())

    if affected_folders:
        with output_funnel.plugged():
            html.write_text(
                _("Affected folders with an explicit reference to this tag "
                  "group and that are affected by the change") + ":")
            _show_affected_folders(affected_folders)
            message += HTML(output_funnel.drain())

    if affected_hosts:
        with output_funnel.plugged():
            html.write_text(
                _("Hosts where this tag group is explicitely set "
                  "and that are effected by the change") + ":")
            _show_affected_hosts(affected_hosts)
            message += HTML(output_funnel.drain())

    if affected_rulesets:
        with output_funnel.plugged():
            html.write_text(
                _("Rulesets that contain rules with references to the changed tags"
                  ) + ":")
            _show_affected_rulesets(affected_rulesets)
            message += HTML(output_funnel.drain())

    if message:
        wato_html_head(title=operation.confirm_title(), breadcrumb=breadcrumb)
        html.open_div(class_="really")
        html.h3(_("Your modifications affect some objects"))
        html.write_text(message)
        html.br()
        html.write_text(
            _("Setup can repair things for you. It can rename tags in folders, host and rules. "
              "Removed tag groups will be removed from hosts and folders, removed tags will be "
              "replaced with the default value for the tag group (for hosts and folders). What "
              "rules concern, you have to decide how to proceed."))
        html.begin_form("confirm", method="POST")

        if affected_rulesets and _is_removing_tags(operation):
            html.br()
            html.b(
                _("Some tags that are used in rules have been removed by you. What "
                  "shall we do with that rules?"))
            html.open_ul()
            html.radiobutton(
                "_repair", "remove", True,
                _("Just remove the affected tags from the rules."))
            html.br()
            html.radiobutton(
                "_repair",
                "delete",
                False,
                _("Delete rules containing tags that have been removed, if tag is used in a positive sense. Just remove that tag if it's used negated."
                  ),
            )
        else:
            html.open_ul()
            html.radiobutton("_repair", "repair", True,
                             _("Fix affected folders, hosts and rules."))

        html.br()
        html.radiobutton("_repair", "abort", False,
                         _("Abort your modifications."))
        html.close_ul()

        html.button("_do_confirm", _("Proceed"), "")
        html.hidden_fields(add_action_vars=True)
        html.end_form()
        html.close_div()
        return False

    return True
示例#21
0
    def page(self):
        # Show outcome of host validation. Do not validate new hosts
        errors = None
        if self._mode == "edit":
            errors = (validate_all_hosts([self._host.name()]).get(
                self._host.name(), []) + self._host.validation_errors())

        if errors:
            html.open_div(class_="info")
            html.open_table(class_="validationerror",
                            boder="0",
                            cellspacing="0",
                            cellpadding="0")
            html.open_tr()

            html.open_td(class_="img")
            html.icon("validation_error")
            html.close_td()

            html.open_td()
            html.open_p()
            html.h3(_("Warning: This host has an invalid configuration!"))
            html.open_ul()
            for error in errors:
                html.li(error)
            html.close_ul()
            html.close_p()

            if html.form_submitted():
                html.br()
                html.b(_("Your changes have been saved nevertheless."))
            html.close_td()

            html.close_tr()
            html.close_table()
            html.close_div()

        lock_message = ""
        locked_hosts = Folder.current().locked_hosts()
        if locked_hosts:
            if locked_hosts is True:
                lock_message = _(
                    "Host attributes locked (You cannot edit this host)")
            elif isinstance(locked_hosts, str):
                lock_message = locked_hosts
        if lock_message:
            html.div(lock_message, class_="info")

        html.begin_form("edit_host", method="POST")
        html.prevent_password_auto_completion()

        basic_attributes = [
            # attribute name, valuepec, default value
            ("host", self._vs_host_name(), self._host.name()),
        ]

        if self._is_cluster():
            basic_attributes += [
                # attribute name, valuepec, default value
                (
                    "nodes",
                    self._vs_cluster_nodes(),
                    self._host.cluster_nodes() if self._host else [],
                ),
            ]

        configure_attributes(
            new=self._mode != "edit",
            hosts={self._host.name(): self._host}
            if self._mode != "new" else {},
            for_what="host" if not self._is_cluster() else "cluster",
            parent=Folder.current(),
            basic_attributes=basic_attributes,
        )

        if self._mode != "edit":
            html.set_focus("host")

        forms.end()
        html.hidden_fields()
        html.end_form()
示例#22
0
def foldable_container(
    *,
    treename: str,
    id_: str,
    isopen: bool,
    title: HTMLContent,
    indent: Union[str, None, bool] = True,
    icon: Optional[str] = None,
    fetch_url: Optional[str] = None,
    title_url: Optional[str] = None,
    title_target: Optional[str] = None,
    padding: int = 15,
    save_state: bool = True,
) -> Iterator[bool]:
    isopen = user.get_tree_state(treename, id_, isopen)
    onclick = foldable_container_onclick(treename, id_, fetch_url, save_state)
    img_id = foldable_container_img_id(treename, id_)
    container_id = foldable_container_id(treename, id_)

    html.open_div(class_=["foldable", "open" if isopen else "closed"])
    html.open_div(class_="foldable_header",
                  onclick=None if title_url else onclick)

    if isinstance(title, HTML):  # custom HTML code
        html.write_text(title)

    else:
        html.open_b(class_=["treeangle", "title"])

        if title_url:
            html.a(title, href=title_url, target=title_target)
        else:
            html.write_text(title)
        html.close_b()

    if icon:
        html.img(
            id_=img_id,
            # Although foldable_sidebar is given via the argument icon it should not be displayed as big as an icon.
            class_=(["treeangle", "title"] +
                    (["icon"] if icon != "foldable_sidebar" else []) +
                    ["open" if isopen else "closed"]),
            src=theme.detect_icon_path(icon, "icon_"),
            onclick=onclick if title_url else None,
        )
    else:
        html.img(
            id_=img_id,
            class_=["treeangle", "open" if isopen else "closed"],
            src=theme.url("images/tree_closed.svg"),
            onclick=onclick if title_url else None,
        )

    html.close_div()

    indent_style = "padding-left: %dpx; " % (padding if indent else 0)
    if indent == "form":
        html.close_td()
        html.close_tr()
        html.close_table()
        indent_style += "margin: 0; "
    html.open_ul(id_=container_id,
                 class_=["treeangle", "open" if isopen else "closed"],
                 style=indent_style)

    yield isopen

    html.close_ul()
    html.close_div()
示例#23
0
 def show(self) -> None:
     html.open_ul(id_="main_menu")
     self._show_main_menu_content()
     html.close_ul()