Arrange to remeber the tab selected in web page
This commit is contained in:
parent
c7cf518477
commit
a1c9a698ee
@ -54,10 +54,10 @@
|
|||||||
<br />
|
<br />
|
||||||
<!--Tabs -->
|
<!--Tabs -->
|
||||||
<div class="tab-container">
|
<div class="tab-container">
|
||||||
<div class="tab tab-active" onclick="openTab(event, 'tab1')">Table</div>
|
<div class="tab tab-active" data-index="0" onclick="openTab(event, 'tab1')">Table</div>
|
||||||
<div class="tab" onclick="openTab(event, 'tab2')">Stacked Bar Graph</div>
|
<div class="tab" data-index="1" onclick="openTab(event, 'tab2')">Stacked Bar Graph</div>
|
||||||
<div class="tab" onclick="openTab(event, 'tab3')">Heat Map</div>
|
<div class="tab" data-index="2" onclick="openTab(event, 'tab3')">Heat Map</div>
|
||||||
<div class="tab" onclick="openTab(event, 'tab4')">Line Graph</div>
|
<div class="tab" data-index="3" onclick="openTab(event, 'tab4')">Line Graph</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="tab1" class="tab-content tab-content-active">
|
<div id="tab1" class="tab-content tab-content-active">
|
||||||
@ -125,18 +125,54 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
window.onload = function(){doNavs();}
|
window.onload = function(){doNavs();}
|
||||||
function openTab(event, tabId){
|
//function openTab(event, tabId){
|
||||||
// Get all elements with class="tab-content" and hide them
|
//// Get all elements with class="tab-content" and hide them
|
||||||
const tabContents = document.querySelectorAll('.tab-content');
|
//const tabContents = document.querySelectorAll('.tab-content');
|
||||||
tabContents.forEach(content => content.classList.remove('tab-content-active'));
|
//tabContents.forEach(content => content.classList.remove('tab-content-active'));
|
||||||
|
|
||||||
|
//// Get all elements with class="tab" and remove the class "tab-active"
|
||||||
|
//const tabs = document.querySelectorAll('.tab');
|
||||||
|
//tabs.forEach(tab => tab.classList.remove('tab-active'));
|
||||||
|
|
||||||
|
//// Show the current tab content, and add an "active" class to the clicked tab
|
||||||
|
//document.getElementById(tabId).classList.add('tab-content-active');
|
||||||
|
//event.target.classList.add('tab-active');}
|
||||||
|
|
||||||
|
function openTab(evt, tabName) {
|
||||||
|
// Declare all variables
|
||||||
|
var i, tab_content, tab;
|
||||||
|
|
||||||
|
// Get all elements with class="tab_content" and hide them
|
||||||
|
tab_content = document.getElementsByClassName("tab-content");
|
||||||
|
for (i = 0; i < tab_content.length; i++) {
|
||||||
|
tab_content[i].style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all elements with class="tab" and remove the class "active"
|
||||||
|
tab = document.getElementsByClassName("tab");
|
||||||
|
for (i = 0; i < tab.length; i++) {
|
||||||
|
tab[i].className = tab[i].className.replace(" tab-active", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the current tab, and add an "active" class to the link that opened the tab
|
||||||
|
document.getElementById(tabName).style.display = "block";
|
||||||
|
evt.currentTarget.className += " tab-active";
|
||||||
|
|
||||||
|
// Store the active tab index
|
||||||
|
sessionStorage.setItem('activeTab', evt.currentTarget.getAttribute("data-index"));
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
// Get the stored tab index from sessionStorage
|
||||||
|
let activeTab = sessionStorage.getItem('activeTab');
|
||||||
|
|
||||||
|
// If there's a stored tab, show that tab
|
||||||
|
if (activeTab !== null) {
|
||||||
|
document.querySelector(`[data-index="$${activeTab}"]`).click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Get all elements with class="tab" and remove the class "tab-active"
|
|
||||||
const tabs = document.querySelectorAll('.tab');
|
|
||||||
tabs.forEach(tab => tab.classList.remove('tab-active'));
|
|
||||||
|
|
||||||
// Show the current tab content, and add an "active" class to the clicked tab
|
|
||||||
document.getElementById(tabId).classList.add('tab-content-active');
|
|
||||||
event.target.classList.add('tab-active');}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<p class="cssvalid">
|
<p class="cssvalid">
|
||||||
|
@ -213,10 +213,6 @@ def create_stacked_bar_graph(data2d, xLabels, yLabels, save_path='stacked_bar_gr
|
|||||||
# Get unique colors for each category
|
# Get unique colors for each category
|
||||||
extended_colors = generate_distinct_colors(len(filtered_xLabels))
|
extended_colors = generate_distinct_colors(len(filtered_xLabels))
|
||||||
|
|
||||||
#print(len(filtered_xLabels))
|
|
||||||
#print(extended_colors)
|
|
||||||
#quit()
|
|
||||||
|
|
||||||
for i, category in enumerate(filtered_xLabels):
|
for i, category in enumerate(filtered_xLabels):
|
||||||
fig.add_trace(go.Bar(
|
fig.add_trace(go.Bar(
|
||||||
name=category,
|
name=category,
|
||||||
@ -244,7 +240,7 @@ def create_stacked_bar_graph(data2d, xLabels, yLabels, save_path='stacked_bar_gr
|
|||||||
# Save the graph to an HTML file
|
# Save the graph to an HTML file
|
||||||
fig.write_html(save_path)
|
fig.write_html(save_path)
|
||||||
# Write it to a var and return the string
|
# Write it to a var and return the string
|
||||||
graph_html = fig.to_html(full_html=False)
|
graph_html = fig.to_html(full_html=False,include_plotlyjs='https://cdn.plot.ly/plotly-latest.min.js')
|
||||||
return graph_html
|
return graph_html
|
||||||
|
|
||||||
def sanitize_and_filter_data(data2d, exclude_labels, xLabels):
|
def sanitize_and_filter_data(data2d, exclude_labels, xLabels):
|
||||||
@ -331,7 +327,7 @@ def create_heatmap(data2d, xLabels, yLabels, save_path='heatmap.html'):
|
|||||||
|
|
||||||
fig.write_html(save_path)
|
fig.write_html(save_path)
|
||||||
# Write it to a var and return the string
|
# Write it to a var and return the string
|
||||||
graph_html = fig.to_html(full_html=False)
|
graph_html = fig.to_html(full_html=False,include_plotlyjs='https://cdn.plot.ly/plotly-latest.min.js')
|
||||||
return graph_html
|
return graph_html
|
||||||
|
|
||||||
|
|
||||||
@ -372,7 +368,7 @@ def create_line_chart(data2d, xLabels, yLabels, save_path='line_chart.html'):
|
|||||||
|
|
||||||
fig.write_html(save_path)
|
fig.write_html(save_path)
|
||||||
# Write it to a var and return the string
|
# Write it to a var and return the string
|
||||||
graph_html = fig.to_html(full_html=False)
|
graph_html = fig.to_html(full_html=False,include_plotlyjs='https://cdn.plot.ly/plotly-latest.min.js')
|
||||||
return graph_html
|
return graph_html
|
||||||
|
|
||||||
|
|
||||||
@ -522,14 +518,11 @@ def read_in_relevant_log_file(file_path,analysis_date=yesterday):
|
|||||||
timestamp = datetime.strptime(timestamp_str, "%Y-%m-%d %H:%M:%S")
|
timestamp = datetime.strptime(timestamp_str, "%Y-%m-%d %H:%M:%S")
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
print(f"ValueError {e} on timestamp extract {timestamp_str}:{entry[1]}")
|
print(f"ValueError {e} on timestamp extract {timestamp_str}:{entry[1]}")
|
||||||
#print(f"{timestamp.date()} {analysis_date.date()}")
|
|
||||||
#quit()
|
|
||||||
if timestamp.date() == analysis_date.date():
|
if timestamp.date() == analysis_date.date():
|
||||||
log_entries.append((timestamp, entry[1]))
|
log_entries.append((timestamp, entry[1]))
|
||||||
else:
|
else:
|
||||||
ignore_record_count += 1
|
ignore_record_count += 1
|
||||||
except UnicodeDecodeError as e:
|
except UnicodeDecodeError as e:
|
||||||
#print(f"{Line} {len(log_entries)} {e} ")
|
|
||||||
pass
|
pass
|
||||||
return [log_entries,skip_record_count,ignore_record_count]
|
return [log_entries,skip_record_count,ignore_record_count]
|
||||||
|
|
||||||
@ -538,8 +531,6 @@ def filter_summary_records(log_entries):
|
|||||||
filtered_log_entries = []
|
filtered_log_entries = []
|
||||||
skipped_entry_count = 0
|
skipped_entry_count = 0
|
||||||
for line in log_entries:
|
for line in log_entries:
|
||||||
#print(line)
|
|
||||||
#quit()
|
|
||||||
if '`' in line[1]:
|
if '`' in line[1]:
|
||||||
filtered_log_entries.append(line)
|
filtered_log_entries.append(line)
|
||||||
else:
|
else:
|
||||||
@ -558,7 +549,6 @@ def parse_data(data):
|
|||||||
# Adjust the field names and parsing logic according to your data format.
|
# Adjust the field names and parsing logic according to your data format.
|
||||||
# Split at the backtick - before it fields split at space, after, fields split at tab
|
# Split at the backtick - before it fields split at space, after, fields split at tab
|
||||||
parts = data.split('`')
|
parts = data.split('`')
|
||||||
#print(f"{parts[0]}:{parts[1]}")
|
|
||||||
fields1 = parts[0].strip().split() if len(parts) > 0 else []
|
fields1 = parts[0].strip().split() if len(parts) > 0 else []
|
||||||
fields2 = parts[1].split('\t') if len(parts) > 1 else []
|
fields2 = parts[1].split('\t') if len(parts) > 1 else []
|
||||||
# then merge them
|
# then merge them
|
||||||
@ -594,8 +584,6 @@ def parse_data(data):
|
|||||||
except:
|
except:
|
||||||
#print(f"error:len:{len(fields)}")
|
#print(f"error:len:{len(fields)}")
|
||||||
return_dict = {}
|
return_dict = {}
|
||||||
#print(return_dict)
|
|
||||||
#quit()
|
|
||||||
return return_dict
|
return return_dict
|
||||||
|
|
||||||
def count_entries_by_hour(log_entries):
|
def count_entries_by_hour(log_entries):
|
||||||
@ -789,16 +777,12 @@ def read_html_from_file(filepath):
|
|||||||
with open(filepath, 'r', encoding='utf-8') as file:
|
with open(filepath, 'r', encoding='utf-8') as file:
|
||||||
html_contents = file.read()
|
html_contents = file.read()
|
||||||
print("reading from html file")
|
print("reading from html file")
|
||||||
#print(len(html_contents))
|
|
||||||
# Get Filepath
|
# Get Filepath
|
||||||
css_path = os.path.dirname(filepath)+"/../css/mailstats.css"
|
css_path = os.path.dirname(filepath)+"/../css/mailstats.css"
|
||||||
#print(css_path)
|
|
||||||
# Read in CSS
|
# Read in CSS
|
||||||
with open(css_path, 'r', encoding='utf-8') as file:
|
with open(css_path, 'r', encoding='utf-8') as file:
|
||||||
css_contents = file.read()
|
css_contents = file.read()
|
||||||
#print(len(css_contents))
|
|
||||||
html_contents = insert_string_after(html_contents,"\n"+css_contents,"<!--css here-->")
|
html_contents = insert_string_after(html_contents,"\n"+css_contents,"<!--css here-->")
|
||||||
#print(len(html_contents))
|
|
||||||
return html_contents
|
return html_contents
|
||||||
|
|
||||||
def read_text_from_file(filepath):
|
def read_text_from_file(filepath):
|
||||||
@ -1036,8 +1020,6 @@ if __name__ == "__main__":
|
|||||||
cursor.execute(delete_query, (analysis_date,)) #Don't forget the syntactic sugar of the extra comma to make it a tuple!
|
cursor.execute(delete_query, (analysis_date,)) #Don't forget the syntactic sugar of the extra comma to make it a tuple!
|
||||||
# Get the number of records deleted
|
# Get the number of records deleted
|
||||||
rows_deleted = cursor.rowcount
|
rows_deleted = cursor.rowcount
|
||||||
print(rows_deleted)
|
|
||||||
#quit()
|
|
||||||
if rows_deleted > 0:
|
if rows_deleted > 0:
|
||||||
print(f"Deleted {rows_deleted} rows for {analysis_date} ")
|
print(f"Deleted {rows_deleted} rows for {analysis_date} ")
|
||||||
except mysql.connector.Error as e:
|
except mysql.connector.Error as e:
|
||||||
@ -1073,10 +1055,6 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
log_file = logs_dir+'current.log'
|
log_file = logs_dir+'current.log'
|
||||||
log_entries,skip_count,ignored_count = read_in_relevant_log_file(log_file,anaysis_date_obj)
|
log_entries,skip_count,ignored_count = read_in_relevant_log_file(log_file,anaysis_date_obj)
|
||||||
# if len(log_entries) == 0:
|
|
||||||
# print(f"No records found in {log_file}")
|
|
||||||
# quit()
|
|
||||||
# else:
|
|
||||||
print(f"Found {len(log_entries)} entries in log for for {anaysis_date_obj.strftime('%Y-%m-%d')} Ignored: {ignored_count} skipped: {skip_count}")
|
print(f"Found {len(log_entries)} entries in log for for {anaysis_date_obj.strftime('%Y-%m-%d')} Ignored: {ignored_count} skipped: {skip_count}")
|
||||||
summary_log_entries,skip_count = filter_summary_records(log_entries)
|
summary_log_entries,skip_count = filter_summary_records(log_entries)
|
||||||
print(f"Found {len(summary_log_entries)} summary entries and skipped {skip_count} entries")
|
print(f"Found {len(summary_log_entries)} summary entries and skipped {skip_count} entries")
|
||||||
@ -1220,7 +1198,6 @@ if __name__ == "__main__":
|
|||||||
match = re.search(spam_pattern, parsed_data['spam-status'])
|
match = re.search(spam_pattern, parsed_data['spam-status'])
|
||||||
if match:
|
if match:
|
||||||
score = float(match.group(1))
|
score = float(match.group(1))
|
||||||
#print(score,SATagLevel)
|
|
||||||
if score < float(SATagLevel):
|
if score < float(SATagLevel):
|
||||||
# Accumulate allowed score (inc negatives?)
|
# Accumulate allowed score (inc negatives?)
|
||||||
hamavg += score
|
hamavg += score
|
||||||
@ -1235,7 +1212,6 @@ if __name__ == "__main__":
|
|||||||
if match:
|
if match:
|
||||||
score = float(match.group(1))
|
score = float(match.group(1))
|
||||||
required = float(match.group(2))
|
required = float(match.group(2))
|
||||||
#print(f"{parsed_data['spam-status']} / {score} {required}")
|
|
||||||
if score >= SARejectLevel:
|
if score >= SARejectLevel:
|
||||||
columnCounts_2d[hour][DelSpam] += 1
|
columnCounts_2d[hour][DelSpam] += 1
|
||||||
columnCounts_2d[ColTotals][DelSpam] += 1
|
columnCounts_2d[ColTotals][DelSpam] += 1
|
||||||
@ -1251,9 +1227,7 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
# Count the qpsmtpd codes
|
# Count the qpsmtpd codes
|
||||||
if parsed_data['error-plugin'].strip() == 'naughty':
|
if parsed_data['error-plugin'].strip() == 'naughty':
|
||||||
#print(f"Found naughty {parsed_data['error-msg']}")
|
|
||||||
if parsed_data['error-msg'].startswith("(dnsbl)"):
|
if parsed_data['error-msg'].startswith("(dnsbl)"):
|
||||||
#print("Found dnsbl")
|
|
||||||
columnCounts_2d[hour][RBLDNS]+= 1
|
columnCounts_2d[hour][RBLDNS]+= 1
|
||||||
columnCounts_2d[ColTotals][RBLDNS]+= 1
|
columnCounts_2d[ColTotals][RBLDNS]+= 1
|
||||||
elif parsed_data['error-msg'].startswith("(karma)"):
|
elif parsed_data['error-msg'].startswith("(karma)"):
|
||||||
@ -1272,12 +1246,9 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
#Now increment the column which the plugin name indicates
|
#Now increment the column which the plugin name indicates
|
||||||
if parsed_data['action'] == '(deny)' and parsed_data['error-plugin']:
|
if parsed_data['action'] == '(deny)' and parsed_data['error-plugin']:
|
||||||
#print(f"Found plugin {parsed_data['error-plugin']}")
|
|
||||||
if parsed_data['error-plugin']:
|
if parsed_data['error-plugin']:
|
||||||
row = search_2d_list(parsed_data['error-plugin'],columnPlugin)
|
row = search_2d_list(parsed_data['error-plugin'],columnPlugin)
|
||||||
#print(row,parsed_data['error-plugin'])
|
|
||||||
if not row == -1:
|
if not row == -1:
|
||||||
#print(f"Found row: {row}")
|
|
||||||
columnCounts_2d[hour][row] += 1
|
columnCounts_2d[hour][row] += 1
|
||||||
columnCounts_2d[ColTotals][row] += 1
|
columnCounts_2d[ColTotals][row] += 1
|
||||||
# a few ad hoc extra extractons of data
|
# a few ad hoc extra extractons of data
|
||||||
@ -1345,6 +1316,7 @@ if __name__ == "__main__":
|
|||||||
print_progress_bar(i, log_len, prefix='Scanning for sub tables:', suffix='Complete', length=50)
|
print_progress_bar(i, log_len, prefix='Scanning for sub tables:', suffix='Complete', length=50)
|
||||||
|
|
||||||
# Match initial connection message
|
# Match initial connection message
|
||||||
|
try:
|
||||||
match = helo_pattern.match(data[1])
|
match = helo_pattern.match(data[1])
|
||||||
if match:
|
if match:
|
||||||
ip = match.group(1)
|
ip = match.group(1)
|
||||||
@ -1354,8 +1326,12 @@ if __name__ == "__main__":
|
|||||||
else:
|
else:
|
||||||
totalexternalsmtpsessions += 1
|
totalexternalsmtpsessions += 1
|
||||||
continue
|
continue
|
||||||
|
except Exception as e:
|
||||||
|
print(f" Helo pattern error {e} {data[1]} {analysis_date}")
|
||||||
|
continue
|
||||||
|
|
||||||
#Pull out Geoip countries for analysis table
|
#Pull out Geoip countries for analysis table
|
||||||
|
try:
|
||||||
match = geoip_pattern.match(data[1])
|
match = geoip_pattern.match(data[1])
|
||||||
if match:
|
if match:
|
||||||
j += 1
|
j += 1
|
||||||
@ -1363,6 +1339,9 @@ if __name__ == "__main__":
|
|||||||
found_countries[country] += 1
|
found_countries[country] += 1
|
||||||
total_countries += 1
|
total_countries += 1
|
||||||
continue
|
continue
|
||||||
|
except Exception as e:
|
||||||
|
print(f" Geoip pattern error {e} {data[1]} {analysis_date}")
|
||||||
|
continue
|
||||||
|
|
||||||
#Pull out DMARC approvals
|
#Pull out DMARC approvals
|
||||||
match = dmarc_pattern.match(data[1])
|
match = dmarc_pattern.match(data[1])
|
||||||
@ -1377,9 +1356,6 @@ if __name__ == "__main__":
|
|||||||
connection_type_counts[connection_type] += 1
|
connection_type_counts[connection_type] += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
#print(columnCounts_2d)
|
|
||||||
#quit()
|
|
||||||
|
|
||||||
#Compute next and previous dates
|
#Compute next and previous dates
|
||||||
day_format = "%Y-%m-%d"
|
day_format = "%Y-%m-%d"
|
||||||
# Convert the time string to a datetime object
|
# Convert the time string to a datetime object
|
||||||
@ -1451,25 +1427,6 @@ if __name__ == "__main__":
|
|||||||
cursor.close()
|
cursor.close()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
# #Add in navigation html - next/previous/see in browser
|
|
||||||
# navigation_str_html = "<div class='linksattop'>\
|
|
||||||
# <a class='prevlink' href='http://${DomainName}/mailstats/mailstats_for_${PreviousDate}.html'>Previous</a>\
|
|
||||||
# <div class='divshowindex'><a class='showindex' href='http://${DomainName}/mailstats/'>Index of files</a></div>\
|
|
||||||
# <a class='nextlink' href='http://${DomainName}/mailstats/mailstats_for_${NextDate}.html'>Next</a>\
|
|
||||||
# </div>"
|
|
||||||
|
|
||||||
# try:
|
|
||||||
# template = PageTemplate(navigation_str_html)
|
|
||||||
# try:
|
|
||||||
# Nav_str = template(PreviousDate=previous_date_str,NextDate=next_date_str,TodayDate=analysis_date,DomainName=DomainName)
|
|
||||||
# except Exception as e:
|
|
||||||
# print(f"Chameleon nav template Exception {e}")
|
|
||||||
# except Exception as e:
|
|
||||||
# print(f"Chameleon nav render Exception {e}")
|
|
||||||
# # And insert it
|
|
||||||
# total_html = insert_string_after(total_html,Nav_str, "<!---Navigation here-->")
|
|
||||||
|
|
||||||
|
|
||||||
# Write the rendered HTML to a file
|
# Write the rendered HTML to a file
|
||||||
output_path = html_page_dir+'mailstats_for_'+analysis_date
|
output_path = html_page_dir+'mailstats_for_'+analysis_date
|
||||||
output_path = output_path.replace(' ','_')
|
output_path = output_path.replace(' ','_')
|
||||||
|
Loading…
Reference in New Issue
Block a user