diff --git a/root/etc/e-smith/templates/etc/httpd/conf/httpd.conf/100mailstats b/root/etc/e-smith/templates/etc/httpd/conf/httpd.conf/100mailstats index 742850c..6dcd0de 100644 --- a/root/etc/e-smith/templates/etc/httpd/conf/httpd.conf/100mailstats +++ b/root/etc/e-smith/templates/etc/httpd/conf/httpd.conf/100mailstats @@ -10,6 +10,7 @@ $OUT .="\n"; $OUT .= qq( # Alias for mailstats + Alias "/mailstats/js" "/opt/mailstats/js" Alias "/mailstats/css" "/opt/mailstats/css" Alias "/mailstats" "/opt/mailstats/html" @@ -29,6 +30,11 @@ AllowOverride None Require all granted + + + AllowOverride None + Require all granted + ); } @@ -36,5 +42,4 @@ { $OUT .= "# mailstats is disabled"; } -} - +} \ No newline at end of file diff --git a/root/opt/mailstats/css/mailstats.css b/root/opt/mailstats/css/mailstats.css index f1f023c..fec72c4 100644 --- a/root/opt/mailstats/css/mailstats.css +++ b/root/opt/mailstats/css/mailstats.css @@ -201,4 +201,10 @@ p.cssvalid,p.htmlvalid {float:left;margin-right:20px} .Incoming, .Junk, .Geoip, .Qpsmtpd, .Viruses, .Blacklist{ flex: 0 1 100%; /* 100% width for 1 column */ } -} \ No newline at end of file +} + +/* Taken from inline in the chameleon templates */ +.maindiv {width:100%;overflow-x:auto;font-size:1cqw} +.traffictable {border-collapse:collapse;width:98%} +.divseeinbrowser{text-align:center;} +.bordercollapse{border-collapse:collapse;} \ No newline at end of file diff --git a/root/opt/mailstats/js/mailstats.js b/root/opt/mailstats/js/mailstats.js new file mode 100644 index 0000000..912e3b2 --- /dev/null +++ b/root/opt/mailstats/js/mailstats.js @@ -0,0 +1,76 @@ +window.onload = function(){doNavs();} +//function openTab(event, tabId){ +//// Get all elements with class="tab-content" and hide them +//const tabContents = document.querySelectorAll('.tab-content'); +//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 LinkCheck(url){ + var http = new XMLHttpRequest(); + http.open('HEAD', url, false); + http.send(); + return http.status!=404; +} +function doNavs() { + var aTags = document.getElementsByTagName('a'), + atl = aTags.length,i; + for (i = 0; i < atl; i++) { + if (aTags[i].innerText == "Previous") { + if (!LinkCheck(aTags[i].href)) { + aTags[i].style.visibility = "hidden"; + } else { + aTags[i].style.visibility = "visible"; + } + } else if (aTags[i].innerText == "Next") { + if (!LinkCheck(aTags[i].href)) { + aTags[i].style.visibility = "hidden"; + } else { + aTags[i].style.visibility = "visible"; + } + } + } +} + +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() { + // Attach click event handler for all divs with the class "tab" + document.querySelectorAll(".tab").forEach(function(tab) { + tab.addEventListener("click", function(event) { + // Get the data-index attribute value + const tabIndex = this.getAttribute("data-index"); + + // Dynamically call openTab with the correct tab parameter + openTab(event, `tab${tabIndex}`); + }); + }); +}); \ No newline at end of file diff --git a/root/opt/mailstats/templates/mailstats-sub-table.html.pt b/root/opt/mailstats/templates/mailstats-sub-table.html.pt index 397ae42..83f2761 100644 --- a/root/opt/mailstats/templates/mailstats-sub-table.html.pt +++ b/root/opt/mailstats/templates/mailstats-sub-table.html.pt @@ -6,7 +6,7 @@
- +
diff --git a/root/opt/mailstats/templates/mailstats.html.pt b/root/opt/mailstats/templates/mailstats.html.pt index d67a085..e9310da 100644 --- a/root/opt/mailstats/templates/mailstats.html.pt +++ b/root/opt/mailstats/templates/mailstats.html.pt @@ -4,39 +4,10 @@ SMEServer Mailstats - - -
+
Previous @@ -54,127 +25,82 @@
-
Table
-
Stacked Bar Graph
-
Heat Map
-
Line Graph
+
Table
+
Line Graph
+
Stacked Bar Graph
+
Scatter Graph
+
Pie Chart
-
-
-
${header}
- - - - - - - - - - - - - - -
Date/TimeHeader
TotalsPercentHour - - - - - - Cell - - - - - - - - Cell - - - - - - - Cell - - - -
- - - -
- ${structure: stacked_bar_graph} -
- -
- ${structure: heatmap} -
- -
- ${structure: line_graph} +
+
+ + + + + + + + + + + + + + + +
Date/TimeHeader
TotalsPercentHour + + + + + + Cell + - + + + + + + Cell + - + + + + + Cell + - + +
+
+
+
+ +
+
-
-
- -
-
-
- + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+ - - + ") + html_contents = insert_string_after(html_contents,"\n","") return html_contents def read_text_from_file(filepath): @@ -1643,7 +1546,7 @@ if __name__ == "__main__": connection_type_counts[connection_type] += 1 #print(f"Count:{connection_type_counts[connection_type]}") continue - + #Compute next and previous dates day_format = "%Y-%m-%d" @@ -1658,10 +1561,27 @@ if __name__ == "__main__": previous_date_str = previous_date.strftime(day_format) # Create graphs of data - yLabels = [f'{i:02d}:00' for i in range(len(columnCounts_2d))] - stacked_Bar_html = create_stacked_bar_graph(columnCounts_2d,columnHeaders,yLabels,html_page_dir+'stacked_bar_'+analysis_date+'.html') - heatmap_html = create_heatmap(columnCounts_2d,columnHeaders,yLabels,html_page_dir+'heatmap_'+analysis_date+'.html') - line_graph_html = create_line_chart(columnCounts_2d,columnHeaders,yLabels,html_page_dir+'line_graph_'+analysis_date+'.html') + + # yLabels = [f'{i:02d}:00' for i in range(len(columnCounts_2d))] + # stacked_Bar_html = create_stacked_bar_graph(columnCounts_2d,columnHeaders,yLabels,html_page_dir+'stacked_bar_'+analysis_date+'.html') + # heatmap_html = create_heatmap(columnCounts_2d,columnHeaders,yLabels,html_page_dir+'heatmap_'+analysis_date+'.html') + # line_graph_html = create_line_chart(columnCounts_2d,columnHeaders,yLabels,html_page_dir+'line_graph_'+analysis_date+'.html') + + columnCounts_2d_dict = transform_to_dict(columnCounts_2d,columnHeaders,analysis_date) + + #Export as json for testing + # with open("/opt/mailstats/html/colCounts_2d.json", "w") as json_file: + # json.dump(columnCounts_2d, json_file) + # with open("/opt/mailstats/html/colCounts_2d-dict", "w") as json_file: + # json.dump(columnCounts_2d_dict, json_file) + # with open("/opt/mailstats/html/keys.json", "w") as json_file: + # json.dump(columnHeaders, json_file) + + if enable_graphs: + create_graph(columnCounts_2d_dict, "line", html_page_dir+"line_graph_"+analysis_date+".png",analysis_date) + create_graph(columnCounts_2d_dict, "bar", html_page_dir+"bar_graph_"+analysis_date+".png",analysis_date) + create_graph(columnCounts_2d_dict, "scatter", html_page_dir+"scatter_graph_"+analysis_date+".png",analysis_date) + create_graph(columnCounts_2d_dict, "pie", html_page_dir+"pie_chart_"+analysis_date+".png",analysis_date) #Now apply the results to the chameleon template - main table # Path to the template file @@ -1682,13 +1602,11 @@ if __name__ == "__main__": reporting_date=analysis_date, title=html_title, version=version_string, nolinks=nolinks, - stacked_bar_graph=stacked_Bar_html, - heatmap=heatmap_html, - line_graph=line_graph_html, PreviousDate=previous_date_str, NextDate=next_date_str, DomainName=DomainName, - SystemName=SystemName + SystemName=SystemName, + enable_graphs=enable_graphs ) except Exception as e: print(f"Chameleon template Exception {e}") @@ -1785,7 +1703,7 @@ if __name__ == "__main__": filepath = html_page_dir+"mailstats_for_"+analysis_date+".html" html_content = read_html_from_file(filepath) # Replace the Navigation by a "See in browser" prompt - replace_str = f"
See in browser
" + replace_str = f"
See in browser
" html_content = replace_between(html_content, "
", ">Next
", replace_str) if not noemailfile: # Write out the email html to a web page diff --git a/smeserver-mailstats.spec b/smeserver-mailstats.spec index 5419adf..bd8e608 100644 --- a/smeserver-mailstats.spec +++ b/smeserver-mailstats.spec @@ -21,9 +21,10 @@ BuildRequires: e-smith-devtools >= 1.13.1-03 Requires: perl-Switch BuildRequires: python36 Requires: python36 -Requires: html2text -Requires: python3-chameleon +Requires: html2text +Requires: python3-chameleon Requires: python3-mysql +Requires: python3-matplotlib AutoReqProv: no %description @@ -126,7 +127,6 @@ sed -i "s|__BUILD_DATE_TIME__|$now|" $RPM_BUILD_ROOT/usr/bin/mailstats.py %pre /usr/bin/pip3 install -q pymysql /usr/bin/pip3 install -q numpy -/usr/bin/pip3 install -q plotly /usr/bin/pip3 install -q pandas %clean