def context_button(self, title, url, icon=None, hot=False, id=None, bestof=None, hover_title='', fkey=None): display = "block" if bestof: counts = config.load_user_file("buttoncounts", {}) weights = counts.items() weights.sort(cmp = lambda a,b: cmp(a[1], b[1])) best = dict(weights[-bestof:]) if id not in best: display="none" self.context_button_hidden = True if not self.context_buttons_open: self.begin_context_buttons() if icon: title = '<img src="images/icon_%s.png">%s' % (icon, title) if id: idtext = " id='%s'" % id else: idtext = "" self.write('<div%s style="display:%s" class="contextlink%s%s" ' % (idtext, display, hot and " hot" or "", (fkey and self.keybindings_enabled) and " button" or "")) self.context_button_hover_code(hot and "_hot" or "") self.write('>') self.write('<a href="%s"' % url) if hover_title: self.write(' title="%s"' % hover_title) if bestof: self.write(' onmousedown="count_context_button(this); document.location=this.href; " ') if fkey and self.keybindings_enabled: title += '<div class=keysym>F%d</div>' % fkey self.add_keybinding([html.F1 + (fkey - 1)], "document.location='%s';" % url) self.write('>%s</a></div>\n' % title)
def top_heading(self, title): if type(self.req.user) == str: login_text = "<b>%s</b> (%s" % (config.user_id, "+".join(config.user_role_ids)) if config.debug: if config.get_language(): login_text += "/%s" % config.get_language() login_text += ')' else: login_text = _("not logged in") self.write('<table class=header><tr><td width="*" class=heading>') self.write('<a href="#" onfocus="if (this.blur) this.blur();" ' 'onclick="this.innerHTML=\'%s\'; document.location.reload();">%s</a></td>' % (_("Reloading..."), title)) self.write('<td style="min-width:240px" class=right><span id=headinfo></span>%s <b id=headertime></b>' % login_text) self.write("<script language=\"javascript\" type=\"text/javascript\">updateHeaderTime()</script>") try: self.help_visible = config.load_user_file("help", False) # cache for later usage except: self.help_visible = False cssclass = self.help_visible and "active" or "passive" self.write('<a id=helpbutton class=%s href="#" onclick="help_toggle();" style="display: none"></a>' % cssclass) self.write("%s</td></tr></table>" % _("<a href=\"http://mathias-kettner.de\"><img src=\"images/mk_logo_small.gif\"/></a>")) self.write("<hr class=header>\n") if config.debug: self.write("<div class=urldebug>%s</div>" % self.makeuri([]))
def ajax_tag_tree(): newconf = int(html.var("conf")) tree_conf = config.load_user_file("virtual_host_tree", {"tree": 0, "cwd": {}}) if type(tree_conf) == int: tree_conf = {"cwd":{}} # convert from old style tree_conf["tree"] = newconf config.save_user_file("virtual_host_tree", tree_conf)
def ajax_tag_tree_enter(): path = html.var("path") and html.var("path").split("|") or [] tree_conf = config.load_user_file("virtual_host_tree", { "tree": 0, "cwd": {} }) tree_conf["cwd"][tree_conf["tree"]] = path config.save_user_file("virtual_host_tree", tree_conf)
def load_acknowledgements(): global g_acknowledgement_time g_acknowledgement_time[config.user_id] = config.load_user_file("acknowledged_notifications", 0) g_modified_time = time.time() if g_acknowledgement_time[config.user_id] == 0: # when this timestamp is first initialized, save the current timestamp as the acknowledge # date. This should considerably reduce the number of log files that have to be searched # when retrieving the list acknowledge_failed_notifications(time.time())
def render_wato_foldertree(): is_slave_site = not wato.is_distributed() and os.path.exists( defaults.check_mk_configdir + "/distributed_wato.mk") if not is_slave_site: if not config.wato_enabled: html.write(_("WATO is disabled.")) return False user_folders = compute_foldertree() # # Render link target selection # selected_topic, selected_target = config.load_user_file( "foldertree", (_('Hosts'), 'allhosts')) views.load_views() dashboard.load_dashboards() topic_views = visuals_by_topic(views.permitted_views().items() + dashboard.permitted_dashboards().items()) topics = [(t, t) for t, s in topic_views] html.select("topic", topics, selected_topic, onchange='wato_tree_topic_changed(this)') html.write('<span class=left>%s</span>' % _('Topic:')) for topic, view_list in topic_views: targets = [] for t, title, name, is_view in view_list: if config.visible_views and name not in config.visible_views: continue if config.hidden_views and name in config.hidden_views: continue if t == topic: if not is_view: name = 'dashboard|' + name targets.append((name, title)) attrs = {} if topic != selected_topic: attrs['style'] = 'display:none' default = '' else: default = selected_target html.select("target_%s" % topic, targets, default, attrs=attrs, onchange='wato_tree_target_changed(this)') html.write('<span class=left>%s</span>' % _('View:')) # Now render the whole tree if user_folders: render_tree_folder(user_folders.values()[0], 'wato_tree_click')
def invalidate_transid(self, id): used_ids = config.load_user_file("transids", []) new_ids = [] now = time.time() for used_id in used_ids: timestamp, rand = used_id.split("/") if now - int(timestamp) < 604800: # 7 * 24 hours new_ids.append(used_id) used_ids.append(id) config.save_user_file("transids", used_ids)
def render_wato_foldertree(): is_slave_site = not wato.is_distributed() and os.path.exists(defaults.check_mk_configdir + "/distributed_wato.mk") if not is_slave_site: if not config.wato_enabled: html.write(_("WATO is disabled.")) return False elif not config.may("wato.use"): html.write(_("You are not allowed to use Check_MK's web configuration GUI.")) return False user_folders = compute_foldertree() # # Render link target selection # selected_topic, selected_target = config.load_user_file("foldertree", (_('Hosts'), 'allhosts')) views.load_views() dashboard.load_dashboards() topic_views = visuals_by_topic(views.permitted_views().items() + dashboard.permitted_dashboards().items()) topics = [ (t, t) for t, s in topic_views ] html.select("topic", topics, selected_topic, onchange = 'wato_tree_topic_changed(this)') html.write('<span class=left>%s</span>' % _('Topic:')) for topic, view_list in topic_views: targets = [] for t, title, name, is_view in view_list: if config.visible_views and name not in config.visible_views: continue if config.hidden_views and name in config.hidden_views: continue if t == topic: if not is_view: name = 'dashboard|' + name targets.append((name, title)) attrs = {} if topic != selected_topic: attrs['style'] = 'display:none' default = '' else: default = selected_target html.select("target_%s" % topic, targets, default, attrs = attrs, onchange = 'wato_tree_target_changed(this)') html.write('<span class=left>%s</span>' % _('View:')) # Now render the whole tree if user_folders: render_tree_folder(user_folders.values()[0], 'wato_tree_click')
def transaction_valid(self): if not self.has_var("_transid"): return False id = self.var("_transid") if not id or id == "-1": return True # automation timestamp, rand = id.split("/") # If age is too old (one week), it is always # invalid: now = time.time() if now - int(timestamp) >= 604800: # 7 * 24 hours return False # Now check, if this id is not yet invalidated return id not in config.load_user_file("transids", [])
def set_rowselection(ident, rows, action): vo = config.load_user_file("rowselection/%s" % selection_id(), {}) if action == 'set': vo[ident] = rows elif action == 'add': vo[ident] = list(set(vo.get(ident, [])).union(rows)) elif action == 'del': vo[ident] = list(set(vo.get(ident, [])) - set(rows)) elif action == 'unset': del vo[ident] if not os.path.exists(config.user_confdir + '/rowselection'): make_nagios_directory(config.user_confdir + '/rowselection') config.save_user_file("rowselection/%s" % selection_id(), vo)
def render_wato_foldertree(): user_folders = compute_foldertree() # # Render link target selection # selected_topic, selected_target = config.load_user_file("foldertree", (_('Hosts'), 'allhosts')) views.load_views() dashboard.load_dashboards() topic_views = visuals_by_topic(views.permitted_views().items() + dashboard.permitted_dashboards().items()) topics = [ (t, t) for t, s in topic_views ] html.select("topic", topics, selected_topic, onchange = 'wato_tree_topic_changed(this)') html.write('<span class=left>%s</span>' % _('Topic:')) for topic, view_list in topic_views: targets = [] for t, title, name, is_view in view_list: if config.visible_views and name not in config.visible_views: continue if config.hidden_views and name in config.hidden_views: continue if t == topic: if not is_view: name = 'dashboard|' + name targets.append((name, title)) attrs = {} if topic != selected_topic: attrs['style'] = 'display:none' default = '' else: default = selected_target html.select("target_%s" % topic, targets, default, attrs = attrs, onchange = 'wato_tree_target_changed(this)') html.write('<span class=left>%s</span>' % _('View:')) # Now render the whole tree if user_folders: render_tree_folder(user_folders.values()[0], 'wato_tree_click')
def render_wato_foldertree(): user_folders = compute_foldertree() # # Render link target selection # selected_topic, selected_target = config.load_user_file("foldertree", (_("Hosts"), "allhosts")) topic_views = views_by_topic() topics = [(t, t) for t, s in topic_views] html.select("topic", topics, selected_topic, onchange="wato_tree_topic_changed(this)") html.write("<span class=left>%s</span>" % _("Topic:")) for topic, views in topic_views: targets = [] for t, title, name in views: if config.visible_views and name not in config.visible_views: continue if config.hidden_views and name in config.hidden_views: continue if t == topic: if topic == _("Dashboards"): name = "dashboard|" + name targets.append((name, title)) attrs = {} if topic != selected_topic: attrs["style"] = "display:none" default = "" else: default = selected_target html.select("target_%s" % topic, targets, default, attrs=attrs, onchange="wato_tree_target_changed(this)") html.write("<span class=left>%s</span>" % _("View:")) # Now render the whole tree if user_folders: render_tree_folder(user_folders.values()[0], "wato_tree_click")
def load_transids(self, lock = False): return config.load_user_file("transids", [], lock)
def ajax_tag_tree_enter(): path = html.var("path") and html.var("path").split("|") or [] tree_conf = config.load_user_file("virtual_host_tree", {"tree": 0, "cwd": {}}) tree_conf["cwd"][tree_conf["tree"]] = path config.save_user_file("virtual_host_tree", tree_conf)
def end(): global table finish_previous() html.unplug() if not table: return # Output-Format "fetch" simply means that all data is being # returned as Python-values to be rendered somewhere else. if table["output_format"] == "fetch": return table["headers"], table["rows"] if table["output_format"] == "csv": do_csv = True csv_separator = html.var("csv_separator", ";") else: do_csv = False if not table["rows"] and table["omit_if_empty"]: table = None return if table["title"] and not do_csv: html.write("<h3>%s</h3>" % table["title"]) if table.get("help") and not do_csv: html.help(table["help"]) if not table["rows"] and not do_csv: html.write("<div class=info>%s</div>" % table["empty_text"]) table = None return table_id = table['id'] rows = table["rows"] # Controls wether or not actions are available for a table search_term = None actions_enabled = (table["searchable"] or table["sortable"]) and not do_csv if actions_enabled: user_opts = config.load_user_file("tableoptions", {}) user_opts.setdefault(table_id, {}) table_opts = user_opts[table_id] # Handle the initial visibility of the actions actions_visible = user_opts[table_id].get('actions_visible', False) if html.var('_%s_actions' % table_id): actions_visible = html.var('_%s_actions' % table_id) == '1' user_opts[table_id]['actions_visible'] = actions_visible if html.var('_%s_reset' % table_id): html.del_var('_%s_search' % table_id) if 'search' in table_opts: del table_opts['search'] # persist if table["searchable"]: # Search is always lower case -> case insensitive search_term = html.var_utf8('_%s_search' % table_id, table_opts.get('search', '')).lower() if search_term: html.set_var('_%s_search' % table_id, search_term) table_opts['search'] = search_term # persist filtered_rows = [] for row, css, state, fixed in rows: if state == "header" or fixed: continue # skip filtering of headers or fixed rows for cell_content, css_classes, colspan in row: if fixed or search_term in cell_content.lower(): filtered_rows.append((row, css, state, fixed)) break # skip other cells when matched rows = filtered_rows if html.var('_%s_reset_sorting' % table_id): html.del_var('_%s_sort' % table_id) if 'sort' in table_opts: del table_opts['sort'] # persist if table["sortable"]: # Now apply eventual sorting settings sort = html.var('_%s_sort' % table_id, table_opts.get('sort')) if sort != None: html.set_var('_%s_sort' % table_id, sort) table_opts['sort'] = sort # persist sort_col, sort_reverse = map(int, sort.split(',', 1)) # remove and remind fixed rows, add to separate list fixed_rows = [] for index, row in enumerate(rows[:]): if row[3] == True: rows.remove(row) fixed_rows.append((index, row)) # Then use natural sorting to sort the list rows.sort(cmp=lambda a, b: cmp(num_split(a[0][sort_col][0]), num_split(b[0][sort_col][0])), reverse=sort_reverse == 1) # Now re-add the removed "fixed" rows to the list again if fixed_rows: for index, row in fixed_rows: rows.insert(index, row) num_rows_unlimited = len(rows) num_cols = len(table["headers"]) # Apply limit after search / sorting etc. limit = table['limit'] if limit is not None: rows = rows[:limit] if not do_csv: html.write('<table class="data') if "css" in table: html.write(" %s" % table["css"]) html.write('">\n') def render_headers(): if table["omit_headers"]: return if do_csv: html.write( csv_separator.join([ html.strip_tags(header) or "" for (header, help, sortable) in table["headers"] ]) + "\n") else: html.write(" <tr>") first_col = True for nr, (header, help, sortable) in enumerate(table["headers"]): text = header if help: header = '<span title="%s">%s</span>' % ( html.attrencode(help), header) if not table["sortable"] or not sortable: html.write(" <th>") else: reverse = 0 sort = html.var('_%s_sort' % table_id) if sort: sort_col, sort_reverse = map(int, sort.split(',', 1)) if sort_col == nr: reverse = sort_reverse == 0 and 1 or 0 html.write( " <th class=\"sort\" title=\"%s\" onclick=\"location.href='%s'\">" % (_('Sort by %s') % text, html.makeactionuri([('_%s_sort' % table_id, '%d,%d' % (nr, reverse))]))) # Add the table action link if first_col: if actions_enabled: if actions_visible: state = '0' help = _('Hide table actions') img = 'table_actions_on' else: state = '1' help = _('Display table actions') img = 'table_actions_off' html.icon_button(html.makeuri([ ('_%s_actions' % table_id, state) ]), help, img, cssclass='toggle_actions') first_col = False html.write("%s</th>\n" % header) html.write(" </tr>\n") # If we have no group headers then paint the headers now if table["rows"] and table["rows"][0][2] != "header": render_headers() if actions_enabled and actions_visible and not do_csv: html.write('<tr class="data even0 actions"><td colspan=%d>' % num_cols) if not html.in_form(): html.begin_form("%s_actions" % table_id) if table["searchable"]: html.write("<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.write("</div>\n") if html.has_var('_%s_sort' % table_id): html.write("<div class=sort>") html.button("_%s_reset_sorting" % table_id, _("Reset sorting")) html.write("</div>\n") if not html.in_form(): html.begin_form("%s_actions" % table_id) html.hidden_fields() html.end_form() html.write('</tr>') odd = "even" for nr, (row, css, state, fixed) in enumerate(rows): if do_csv: html.write( csv_separator.join([ html.strip_tags(cell_content) for cell_content, css_classes, colspan in row ])) html.write("\n") else: # HTML output # 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.write( ' <tr class="groupheader"><td colspan=%d><br>%s</td></tr>' % (num_cols, row)) odd = "even" render_headers() continue odd = odd == "odd" and "even" or "odd" html.write(' <tr class="data %s%d' % (odd, state)) if css: html.write(' %s' % css) html.write('">\n') for cell_content, css_classes, colspan in row: colspan = colspan and (' colspan="%d"' % colspan) or '' html.write(" <td%s%s>" % (css_classes and (" class='%s'" % css_classes) or "", colspan)) html.write(cell_content) html.write("</td>\n") html.write("</tr>\n") if table["searchable"] and search_term and not rows and not do_csv: html.write( '<tr class="data odd0 no_match"><td colspan=%d>%s</td></tr>' % (num_cols, _('Found no matching rows. Please try another search term.'))) if not do_csv: html.write("</table>\n") if limit is not None and num_rows_unlimited > limit and not do_csv: html.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, html.makeuri([('limit', 'none')]))) if actions_enabled and not do_csv: config.save_user_file("tableoptions", user_opts) table = None
def load_ex_level(): return config.load_user_file("bi_treestate", (None, ))[0]
def render_wato_foldertree(): html.live.set_prepend_site(True) query = "GET hosts\n" \ "Stats: state >= 0\n" \ "Columns: filename" hosts = html.live.query(query) html.live.set_prepend_site(False) hosts.sort() def get_folder(path, num = 0): wato_folder = {} if wato.folder_config_exists(wato.root_dir + path): wato_folder = wato.load_folder(wato.root_dir + path, childs = False) return { 'title': wato_folder.get('title', path.split('/')[-1]), '.path': path, '.num_hosts': num, '.folders': {}, } # After the query we have a list of lists where each # row is a folder with the number of hosts on this level. # # Now get number of hosts by folder # Count all childs for each folder user_folders = {} for site, wato_folder, num in hosts: # Remove leading /wato/ wato_folder = wato_folder[6:] # Loop through all levels of this folder to add the # host count to all parent levels folder_parts = wato_folder.split('/') for num_parts in range(0, len(folder_parts)): this_folder = '/'.join(folder_parts[:num_parts]) if this_folder not in user_folders: user_folders[this_folder] = get_folder(this_folder, num) else: user_folders[this_folder]['.num_hosts'] += num # # Now build the folder tree # for folder_path, folder in sorted(user_folders.items(), reverse = True): if not folder_path: continue folder_parts = folder_path.split('/') parent_folder = '/'.join(folder_parts[:-1]) user_folders[parent_folder]['.folders'][folder_path] = folder del user_folders[folder_path] # # Render link target selection # selected_topic, selected_target = config.load_user_file("foldertree", (_('Hosts'), 'allhosts')) topic_views = views_by_topic() topics = [ (t, t) for t, s in topic_views ] html.select("topic", topics, selected_topic, onchange = 'wato_tree_topic_changed(this)') html.write('<span class=left>%s</span>' % _('Topic:')) for topic, views in topic_views: targets = [] for t, title, name in views: if config.visible_views and name not in config.visible_views: continue if config.hidden_views and name in config.hidden_views: continue if t == topic: if topic == _('Dashboards'): name = 'dashboard|' + name targets.append((name, title)) attrs = {} if topic != selected_topic: attrs['style'] = 'display:none' default = '' else: default = selected_target html.select("target_%s" % topic, targets, default, attrs = attrs, onchange = 'wato_tree_target_changed(this)') html.write('<span class=left>%s</span>' % _('View:')) # Now render the whole tree if user_folders: render_tree_folder(user_folders[''])
def load_tree_states(): global treestates global treestates_for_id if html.id is not treestates_for_id: treestates = config.load_user_file("treestates", {}) treestates_for_id = html.id
def get_button_counts(self): return config.load_user_file("buttoncounts", {})
def load_tree_states(self): if self.id is not self.treestates_for_id: self.treestates = config.load_user_file("treestates", {}) self.treestates_for_id = self.id
def end(): global table finish_previous() html.unplug() if not table: return if not table["rows"] and table["omit_if_empty"]: table = None return if table["title"]: html.write("<h3>%s</h3>" % table["title"]) if table.get("help"): html.help(table["help"]) if not table["rows"]: html.write("<div class=info>%s</div>" % table["empty_text"]) table = None return table_id = table["id"] rows = table["rows"] # Controls wether or not actions are available for a table actions_enabled = table["searchable"] if actions_enabled: user_opts = config.load_user_file("tableoptions", {}) user_opts.setdefault(table_id, {}) table_opts = user_opts[table_id] # Handle the initial visibility of the actions actions_visible = user_opts[table_id].get("actions_visible", False) if html.var("_%s_actions" % table_id): actions_visible = html.var("_%s_actions" % table_id) == "1" user_opts[table_id]["actions_visible"] = actions_visible if html.var("_%s_reset" % table_id): html.del_var("_%s_search" % table_id) if "search" in table_opts: del table_opts["search"] # persist # Search is always lower case -> case insensitive search_term = html.var("_%s_search" % table_id, table_opts.get("search", "")).lower() if search_term: html.set_var("_%s_search" % table_id, search_term) table_opts["search"] = search_term # persist filtered_rows = [] for row, css, state in rows: if state == "header": continue for cell_content, css_classes in row: if search_term in cell_content.lower(): filtered_rows.append((row, css, state)) break # skip other cells when matched rows = filtered_rows num_rows_unlimited = len(rows) num_cols = len(table["headers"]) # Apply limit after search / sorting etc. limit = table["limit"] if limit is not None: rows = rows[:limit] html.write('<table class="data') if "css" in table: html.write(" %s" % table["css"]) html.write('">\n') def render_headers(): html.write(" <tr class=DEPP>") first_col = True for header, help in table["headers"]: if help: header = '<span title="%s">%s</span>' % (html.attrencode(help), header) html.write(" <th>") # Add the table action link if first_col: if actions_enabled: if actions_visible: state = "0" help = _("Hide table actions") img = "table_actions_on" else: state = "1" help = _("Display table actions") img = "table_actions_off" html.icon_button( html.makeuri([("_%s_actions" % table_id, state)]), help, img, cssclass="toggle_actions" ) first_col = False html.write("%s</th>\n" % header) html.write(" </tr>\n") # If we have no group headers then paint the headers now if table["rows"] and table["rows"][0][2] != "header": render_headers() if actions_enabled and actions_visible: html.write('<tr class="data even0 actions"><td colspan=%d>' % num_cols) html.begin_form("%s_actions" % table_id) if table["searchable"]: html.write("<div class=search>") html.text_input("_%s_search" % table_id) html.button("_%s_submit" % table_id, _("Search")) html.button("_%s_reset" % table_id, _("Reset")) html.set_focus("_%s_search" % table_id) html.write("</div>\n") html.hidden_fields() html.end_form() html.write("</tr>") odd = "even" # TODO: Sorting for nr, (row, css, state) in enumerate(rows): # 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.write(' <tr class="groupheader"><td colspan=%d><br>%s</td></tr>' % (num_cols, row)) odd = "even" render_headers() continue odd = odd == "odd" and "even" or "odd" html.write(' <tr class="data %s%d' % (odd, state)) if css: html.write(" %s" % css) html.write('">\n') for cell_content, css_classes in row: html.write(" <td%s>" % (css_classes and (" class='%s'" % css_classes) or "")) html.write(cell_content) html.write("</td>\n") html.write("</tr>\n") if actions_enabled and search_term and not rows: html.write( '<tr class="data odd0 no_match"><td colspan=%d>%s</td></tr>' % (num_cols, _("Found no matching rows. Please try another search term.")) ) html.write("</table>\n") if limit is not None and num_rows_unlimited > limit: html.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, html.makeuri([("limit", "none")])) ) if actions_enabled: config.save_user_file("tableoptions", user_opts) table = None
def end(): global table finish_previous() html.unplug() if not table: return if not table["rows"] and table["omit_if_empty"]: table = None return if table["title"]: html.write("<h3>%s</h3>" % table["title"]) if table.get("help"): html.help(table["help"]) if not table["rows"]: html.write("<div class=info>%s</div>" % table["empty_text"]) table = None return table_id = table['id'] rows = table["rows"] # Controls wether or not actions are available for a table actions_enabled = table["searchable"] if actions_enabled: user_opts = config.load_user_file("tableoptions", {}) user_opts.setdefault(table_id, {}) table_opts = user_opts[table_id] # Handle the initial visibility of the actions actions_visible = user_opts[table_id].get('actions_visible', False) if html.var('_%s_actions' % table_id): actions_visible = html.var('_%s_actions' % table_id) == '1' user_opts[table_id]['actions_visible'] = actions_visible if html.var('_%s_reset' % table_id): html.del_var('_%s_search' % table_id) if 'search' in table_opts: del table_opts['search'] # persist # Search is always lower case -> case insensitive search_term = html.var('_%s_search' % table_id, table_opts.get('search', '')).lower() if search_term: html.set_var('_%s_search' % table_id, search_term) table_opts['search'] = search_term # persist filtered_rows = [] for row, css in rows: for cell_content, css_classes in row: if search_term in cell_content.lower(): filtered_rows.append((row, css)) break # skip other cells when matched rows = filtered_rows num_rows_unlimited = len(rows) num_cols = len(table["headers"]) # Apply limit after search / sorting etc. limit = table['limit'] if limit is not None: rows = rows[:limit] html.write('<table class="data') if "css" in table: html.write(" %s" % table["css"]) html.write('">\n') html.write(" <tr>") first_col = True for header, help in table["headers"]: if help: header = '<span title="%s">%s</span>' % (html.attrencode(help), header) html.write(" <th>") # Add the table action link if first_col: if actions_enabled: if actions_visible: state = '0' help = _('Hide table actions') img = 'table_actions_on' else: state = '1' help = _('Display table actions') img = 'table_actions_off' html.icon_button(html.makeuri([('_%s_actions' % table_id, state)]), help, img, cssclass = 'toggle_actions') first_col = False html.write("%s</th>\n" % header) html.write(" </tr>\n") if actions_enabled and actions_visible: html.write('<tr class="data even0 actions"><td colspan=%d>' % num_cols) html.begin_form("%s_actions" % table_id) if table["searchable"]: html.write("<div class=search>") html.text_input("_%s_search" % table_id) html.button("_%s_submit" % table_id, _("Search")) html.button("_%s_reset" % table_id, _("Reset")) html.set_focus("_%s_search" % table_id) html.write("</div>\n") html.hidden_fields() html.end_form() html.write('</tr>') odd = "even" # TODO: Sorting for row, css in rows: odd = odd == "odd" and "even" or "odd" html.write(' <tr class="data %s0' % odd) if css: html.write(' %s' % css) html.write('">\n') for cell_content, css_classes in row: html.write(" <td%s>" % (css_classes and (" class='%s'" % css_classes) or "")) html.write(cell_content) html.write("</td>\n") html.write("</tr>\n") if actions_enabled and search_term and not rows: html.write('<tr class="data odd0 no_match"><td colspan=%d>%s</td></tr>' % (num_cols, _('Found no matching rows. Please try another search term.'))) html.write("</table>\n") if limit is not None and num_rows_unlimited > limit: html.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, html.makeuri([('limit', 'none')]))) if actions_enabled: config.save_user_file("tableoptions", user_opts) table = None
def load_tree_states(self): if self.treestates == None: self.treestates = config.load_user_file("treestates", {})
def get_rowselection(ident): vo = config.load_user_file("rowselection/%s" % selection_id(), {}) return vo.get(ident, [])
def load_help_visible(self): try: self.help_visible = config.load_user_file("help", False) # cache for later usage except: pass
def end(): global table finish_previous() html.unplug() if not table: return # Output-Format "fetch" simply means that all data is being # returned as Python-values to be rendered somewhere else. if table["output_format"] == "fetch": return table["headers"], table["rows"] if table["output_format"] == "csv": do_csv = True csv_separator = html.var("csv_separator", ";") else: do_csv = False if not table["rows"] and table["omit_if_empty"]: table = None return if table["title"] and not do_csv: html.write("<h3>%s</h3>" % table["title"]) if table.get("help") and not do_csv: html.help(table["help"]) if not table["rows"] and not do_csv: html.write("<div class=info>%s</div>" % table["empty_text"]) table = None return table_id = table['id'] rows = table["rows"] # Controls wether or not actions are available for a table search_term = None actions_enabled = (table["searchable"] or table["sortable"]) and not do_csv if actions_enabled: user_opts = config.load_user_file("tableoptions", {}) user_opts.setdefault(table_id, {}) table_opts = user_opts[table_id] # Handle the initial visibility of the actions actions_visible = user_opts[table_id].get('actions_visible', False) if html.var('_%s_actions' % table_id): actions_visible = html.var('_%s_actions' % table_id) == '1' user_opts[table_id]['actions_visible'] = actions_visible if html.var('_%s_reset' % table_id): html.del_var('_%s_search' % table_id) if 'search' in table_opts: del table_opts['search'] # persist if table["searchable"]: # Search is always lower case -> case insensitive search_term = html.var('_%s_search' % table_id, table_opts.get('search', '')).lower() if search_term: html.set_var('_%s_search' % table_id, search_term) table_opts['search'] = search_term # persist filtered_rows = [] for row, css, state, fixed in rows: if state == "header" or fixed: continue # skip filtering of headers or fixed rows for cell_content, css_classes, colspan in row: if fixed or search_term in cell_content.lower(): filtered_rows.append((row, css, state, fixed)) break # skip other cells when matched rows = filtered_rows if html.var('_%s_reset_sorting' % table_id): html.del_var('_%s_sort' % table_id) if 'sort' in table_opts: del table_opts['sort'] # persist if table["sortable"]: # Now apply eventual sorting settings sort = html.var('_%s_sort' % table_id, table_opts.get('sort')) if sort != None: html.set_var('_%s_sort' % table_id, sort) table_opts['sort'] = sort # persist sort_col, sort_reverse = map(int, sort.split(',', 1)) # remove and remind fixed rows, add to separate list fixed_rows = [] for index, row in enumerate(rows[:]): if row[3] == True: rows.remove(row) fixed_rows.append((index, row)) # Then use natural sorting to sort the list rows.sort(cmp=lambda a, b: cmp(num_split(a[0][sort_col][0]), num_split(b[0][sort_col][0])), reverse=sort_reverse==1) # Now re-add the removed "fixed" rows to the list again if fixed_rows: for index, row in fixed_rows: rows.insert(index, row) num_rows_unlimited = len(rows) num_cols = len(table["headers"]) # Apply limit after search / sorting etc. limit = table['limit'] if limit is not None: rows = rows[:limit] if not do_csv: html.write('<table class="data') if "css" in table: html.write(" %s" % table["css"]) html.write('">\n') def render_headers(): if table["omit_headers"]: return if do_csv: html.write(csv_separator.join([html.strip_tags(header) or "" for (header, help, sortable) in table["headers"]]) + "\n") else: html.write(" <tr>") first_col = True for nr, (header, help, sortable) in enumerate(table["headers"]): text = header if help: header = '<span title="%s">%s</span>' % (html.attrencode(help), header) if not table["sortable"] or not sortable: html.write(" <th>") else: reverse = 0 sort = html.var('_%s_sort' % table_id) if sort: sort_col, sort_reverse = map(int, sort.split(',', 1)) if sort_col == nr: reverse = sort_reverse == 0 and 1 or 0 html.write(" <th class=\"sort\" title=\"%s\" onclick=\"location.href='%s'\">" % (_('Sort by %s') % text, html.makeactionuri([('_%s_sort' % table_id, '%d,%d' % (nr, reverse))]))) # Add the table action link if first_col: if actions_enabled: if actions_visible: state = '0' help = _('Hide table actions') img = 'table_actions_on' else: state = '1' help = _('Display table actions') img = 'table_actions_off' html.icon_button(html.makeuri([('_%s_actions' % table_id, state)]), help, img, cssclass = 'toggle_actions') first_col = False html.write("%s</th>\n" % header) html.write(" </tr>\n") # If we have no group headers then paint the headers now if table["rows"] and table["rows"][0][2] != "header": render_headers() if actions_enabled and actions_visible and not do_csv: html.write('<tr class="data even0 actions"><td colspan=%d>' % num_cols) if not html.in_form(): html.begin_form("%s_actions" % table_id) if table["searchable"]: html.write("<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.write("</div>\n") if html.has_var('_%s_sort' % table_id): html.write("<div class=sort>") html.button("_%s_reset_sorting" % table_id, _("Reset sorting")) html.write("</div>\n") if not html.in_form(): html.begin_form("%s_actions" % table_id) html.hidden_fields() html.end_form() html.write('</tr>') odd = "even" for nr, (row, css, state, fixed) in enumerate(rows): if do_csv: html.write(csv_separator.join([html.strip_tags(cell_content) for cell_content, css_classes, colspan in row ])) html.write("\n") else: # HTML output # 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.write(' <tr class="groupheader"><td colspan=%d><br>%s</td></tr>' % (num_cols, row)) odd = "even" render_headers() continue odd = odd == "odd" and "even" or "odd" html.write(' <tr class="data %s%d' % (odd, state)) if css: html.write(' %s' % css) html.write('">\n') for cell_content, css_classes, colspan in row: colspan = colspan and (' colspan="%d"' % colspan) or '' html.write(" <td%s%s>" % (css_classes and (" class='%s'" % css_classes) or "", colspan)) html.write(cell_content) html.write("</td>\n") html.write("</tr>\n") if table["searchable"] and search_term and not rows and not do_csv: html.write('<tr class="data odd0 no_match"><td colspan=%d>%s</td></tr>' % (num_cols, _('Found no matching rows. Please try another search term.'))) if not do_csv: html.write("</table>\n") if limit is not None and num_rows_unlimited > limit and not do_csv: html.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, html.makeuri([('limit', 'none')]))) if actions_enabled and not do_csv: config.save_user_file("tableoptions", user_opts) table = None
def render_wato_foldertree(): html.live.set_prepend_site(True) query = "GET hosts\n" \ "Stats: state >= 0\n" \ "Columns: filename" hosts = html.live.query(query) html.live.set_prepend_site(False) hosts.sort() def get_folder(path, num=0): wato_folder = {} if wato.folder_config_exists(wato.root_dir + path): wato_folder = wato.load_folder(wato.root_dir + path, childs=False) return { 'title': wato_folder.get('title', path.split('/')[-1]), '.path': path, '.num_hosts': num, '.folders': {}, } # After the query we have a list of lists where each # row is a folder with the number of hosts on this level. # # Now get number of hosts by folder # Count all childs for each folder user_folders = {} for site, wato_folder, num in hosts: # Remove leading /wato/ wato_folder = wato_folder[6:] # Loop through all levels of this folder to add the # host count to all parent levels folder_parts = wato_folder.split('/') for num_parts in range(0, len(folder_parts)): this_folder = '/'.join(folder_parts[:num_parts]) if this_folder not in user_folders: user_folders[this_folder] = get_folder(this_folder, num) else: user_folders[this_folder]['.num_hosts'] += num # # Now build the folder tree # for folder_path, folder in sorted(user_folders.items(), reverse=True): if not folder_path: continue folder_parts = folder_path.split('/') parent_folder = '/'.join(folder_parts[:-1]) user_folders[parent_folder]['.folders'][folder_path] = folder del user_folders[folder_path] # # Render link target selection # selected_topic, selected_target = config.load_user_file( "foldertree", (_('Hosts'), 'allhosts')) topic_views = views_by_topic() topics = [(t, t) for t, s in topic_views] html.select("topic", topics, selected_topic, onchange='wato_tree_topic_changed(this)') html.write('<span class=left>%s</span>' % _('Topic:')) for topic, views in topic_views: targets = [] for t, title, name in views: if config.visible_views and name not in config.visible_views: continue if config.hidden_views and name in config.hidden_views: continue if t == topic: if topic == _('Dashboards'): name = 'dashboard|' + name targets.append((name, title)) attrs = {} if topic != selected_topic: attrs['style'] = 'display:none' default = '' else: default = selected_target html.select("target_%s" % topic, targets, default, attrs=attrs, onchange='wato_tree_target_changed(this)') html.write('<span class=left>%s</span>' % _('View:')) # Now render the whole tree if user_folders: render_tree_folder(user_folders[''])
def load_assumptions(): global g_assumptions g_assumptions = config.load_user_file("bi_assumptions", {})
def load_transids(self): return config.load_user_file("transids", [])