diff --git a/templates/muncollapse/.gitignore b/templates/muncollapse/.gitignore new file mode 100644 index 00000000..db722b8d --- /dev/null +++ b/templates/muncollapse/.gitignore @@ -0,0 +1,6 @@ +static/img/ +static/css/bootstrap.min.css +static/js/bootstrap.min.js +static/js/jquery.min.js +static/js/lazysizes.min.js +static/js/typeahead.bundle.min.js diff --git a/templates/munstrap4/LICENSE b/templates/muncollapse/LICENSE similarity index 100% rename from templates/munstrap4/LICENSE rename to templates/muncollapse/LICENSE diff --git a/templates/muncollapse/Makefile b/templates/muncollapse/Makefile new file mode 100644 index 00000000..955c7ead --- /dev/null +++ b/templates/muncollapse/Makefile @@ -0,0 +1,54 @@ +# MunCollapsible +# +# Makefile for the MunCollapsible template. + +# HTTP Fetch program to use. Called as $(HTTP_FETCH) +# +# Swap the comments to use curl instead. +HTTP_FETCH = wget -nv -O +#HTTP_FETCH = curl -s -w "%{http_code} - %{filename_effective} - %{size_download} bytes\n" -o + + +# The versions of the external libraries to use. +BOOTSTRAP_VERSION = 4.4.1 +JQUERY_VERSION = 3.4.1.slim +TYPEAHEAD_VERSION = latest + +FAVICON_FILES := android-chrome-144x144.png android-chrome-192x192.png android-chrome-36x36.png android-chrome-48x48.png android-chrome-72x72.png android-chrome-96x96.png apple-touch-icon-114x114.png apple-touch-icon-120x120.png apple-touch-icon-144x144.png apple-touch-icon-152x152.png apple-touch-icon-180x180.png apple-touch-icon-57x57.png apple-touch-icon-60x60.png apple-touch-icon-72x72.png apple-touch-icon-76x76.png apple-touch-icon-precomposed.png apple-touch-icon.png browserconfig.xml favicon-16x16.png favicon-194x194.png favicon-32x32.png favicon-96x96.png favicon.ico manifest.json mstile-144x144.png mstile-150x150.png mstile-310x150.png mstile-310x310.png mstile-70x70.png +FAVICON_BASEURL = https://raw.githubusercontent.com/munin-monitoring/munin/master/web/static/img/favicons/ + +LOGO_URL = https://raw.githubusercontent.com/munin-monitoring/munin/master/web/static/img/logo-h.png + +BOOTSTRAP_CSS_URL = https://stackpath.bootstrapcdn.com/bootstrap/$(BOOTSTRAP_VERSION)/css/bootstrap.min.css +BOOTSTRAP_JS_URL = https://stackpath.bootstrapcdn.com/bootstrap/$(BOOTSTRAP_VERSION)/js/bootstrap.bundle.min.js +JQUERY_JS_URL = https://code.jquery.com/jquery-$(JQUERY_VERSION).min.js +TYPEAHEAD_JS_URL = https://twitter.github.io/typeahead.js/releases/$(TYPEAHEAD_VERSION)/typeahead.bundle.js +LAZYSIZES_URL = http://afarkas.github.io/lazysizes/lazysizes.min.js + +CWD := $(abspath $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))) + + +main: + @echo $(CWD) + @echo Downloading External Libraries... + + $(HTTP_FETCH) $(CWD)/static/css/bootstrap.min.css $(BOOTSTRAP_CSS_URL) + $(HTTP_FETCH) $(CWD)/static/js/bootstrap.min.js $(BOOTSTRAP_JS_URL) + $(HTTP_FETCH) $(CWD)/static/js/jquery.min.js $(JQUERY_JS_URL) + $(HTTP_FETCH) $(CWD)/static/js/typeahead.bundle.min.js $(TYPEAHEAD_JS_URL) + $(HTTP_FETCH) $(CWD)/static/js/lazysizes.min.js $(LAZYSIZES_URL) + + @echo Downloading Logo... + @mkdir -p $(CWD)/static/img + $(HTTP_FETCH) $(CWD)/static/img/logo-munin.png $(LOGO_URL) + + @echo Downloading Favicon Files... + + @mkdir -p $(CWD)/static/img/favicon + @for file in ${FAVICON_FILES}; do \ + eval $(HTTP_FETCH) $(CWD)/static/img/favicon/$${file} $(FAVICON_BASEURL)$${file}; \ + done + + + + \ No newline at end of file diff --git a/templates/muncollapse/README.md b/templates/muncollapse/README.md new file mode 100644 index 00000000..80f3f3a3 --- /dev/null +++ b/templates/muncollapse/README.md @@ -0,0 +1,133 @@ +# MunCollapse + +Alternative Munin 2.x templates based on Twitter Bootstrap using collapsibles. + +Based on some of the work of "Munstrap" by [Jonny McCullagh](https://github.com/jonnymccullagh), [munin-monitoring/contrib](https://github.com/munin-monitoring/contrib/tree/master/templates/munstrap) repo. + +#### Overview Sample Image + + +[Semi-Live Demo](https://jtsage.dev/munin-demo/) - For the purposes of this demo only, the data is static and the zoom functionality is disabled. + +--- + +## Installation + +### 1. Clone the munin-monitoring/contrib repo to a temporary location: + +``` +$ cd /opt +$ git clone https://github.com/munin-monitoring/contrib.git +``` + +### 2. Fetch the template libraries + +``` +$ cd /opt/contrib/templates/muncollapse/ +$ make +``` + +### 3. Place the template in an appropriate safe place + +Ubuntu shown - other distros may prefer ```/usr/local/share/munin/...``` + +``` +$ mkdir /usr/share/munin/template +$ mkdir /usr/share/munin/template/muncollapse +``` +__NOTE__: If this step fails, your munin installation may use ```/usr/local/share/munin/...``` instead! + +``` +$ cp -r /opt/contrib/templates/muncollapse/templates /usr/share/munin/template/muncollapse/ +$ cp -r /opt/contrib/templates/muncollapse/static /usr/share/munin/template/muncollapse/ +``` + +### 4. Edit your ```munin.conf``` file. + +Typically located at ```/etc/munin.conf``` + +__FIND AND CHANGE:__ (near the top of the file) + +``` +# Where to look for the HTML templates +# +#tmpldir /etc/munin/templates + +# Where to look for the static www files +# +#staticdir /etc/munin/static +``` + +__TO:__ +``` +# Where to look for the HTML templates +# +tmpldir /usr/share/munin/template/muncollapse/templates + +# Where to look for the static www files +# +staticdir /usr/share/munin/template/muncollapse/static +``` + +### 5. [Optional / Recommended] Clean out the old generated files. + +This isn't really required, but there will likely be orphaned files. The location of these files can be found in your ```munin.conf``` file, with the ```htmldir``` directive. + +__NOTE:__ Ubuntu shown, other distributions may be in ```/var/www/munin/``` + +``` +$ rm -rf /var/cache/munin/www/* +``` + +### 6. Wait Patiently + +```munin-update``` will regenerate the files the next time it runs. By default, this is on the :05 minute tick for most installations. If you do not have new files within 10 minutes, be sure to check ```munin-update.log``` and find out what went wrong. + +--- + +## Revert to Official Munin Template + +### 1. Edit your ```munin.conf``` file. + +Typically located at ```/etc/munin.conf``` + +__FIND AND CHANGE:__ (near the top of the file - comment these lines out!) + +# Where to look for the HTML templates +# +#tmpldir /usr/share/munin/template/muncollapse/templates + +# Where to look for the static www files +# +#staticdir /usr/share/munin/template/muncollapse/static + +### 2. [Optional / Recommended] Clean up + +Remove the files from step #1 & #3 above, and repeat step #5 & #6. + +--- + +## Samples + +#### View of a group: + + +#### View of a specific node: + + + +#### Zoom feature: + + + +--- + +## Munin Compatibility + +a/n: I am unsure of the compatibility with Munin 3. Most things will work from what I've read, but the navigation may be slightly funky. + +--- + +### Browser Compatibility + +For this template set, Internet Explorer support has been dropped for the dynamic zoom functions. Everything else should work across all browsers. diff --git a/templates/muncollapse/sample-image/sample-group.png b/templates/muncollapse/sample-image/sample-group.png new file mode 100644 index 00000000..d37c45b2 Binary files /dev/null and b/templates/muncollapse/sample-image/sample-group.png differ diff --git a/templates/muncollapse/sample-image/sample-home.png b/templates/muncollapse/sample-image/sample-home.png new file mode 100644 index 00000000..7cbf22c6 Binary files /dev/null and b/templates/muncollapse/sample-image/sample-home.png differ diff --git a/templates/muncollapse/sample-image/sample-node.png b/templates/muncollapse/sample-image/sample-node.png new file mode 100644 index 00000000..4273aff4 Binary files /dev/null and b/templates/muncollapse/sample-image/sample-node.png differ diff --git a/templates/muncollapse/sample-image/sample-zoom.png b/templates/muncollapse/sample-image/sample-zoom.png new file mode 100644 index 00000000..19b857f0 Binary files /dev/null and b/templates/muncollapse/sample-image/sample-zoom.png differ diff --git a/templates/munstrap4/static/css/bootstrap4.min.css b/templates/muncollapse/static/css/bootstrap4.min.css similarity index 100% rename from templates/munstrap4/static/css/bootstrap4.min.css rename to templates/muncollapse/static/css/bootstrap4.min.css diff --git a/templates/munstrap4/static/css/style-munstrap.css b/templates/muncollapse/static/css/style-munstrap.css similarity index 97% rename from templates/munstrap4/static/css/style-munstrap.css rename to templates/muncollapse/static/css/style-munstrap.css index 4ef1a07e..29e6c2a3 100644 --- a/templates/munstrap4/static/css/style-munstrap.css +++ b/templates/muncollapse/static/css/style-munstrap.css @@ -18,7 +18,7 @@ div.service-alert { } img#zoom_image { - margin-bottom: 15px; + border: none; } ul.groupview, ul.groupview ul { @@ -27,11 +27,9 @@ ul.groupview, ul.groupview ul { .munin-icon { background: url(../img/logo-munin.png) left top; - margin-top: -6px; - width: 35px; - height: 35px; + width: 115px; + height: 30px; display: block; - float: left; } diff --git a/templates/muncollapse/static/js/dynazoom.js b/templates/muncollapse/static/js/dynazoom.js new file mode 100644 index 00000000..15c5dbf0 --- /dev/null +++ b/templates/muncollapse/static/js/dynazoom.js @@ -0,0 +1,239 @@ +/* MunCollapse Template DynaZoom JavaScript File +* +* Notes: +* +* - No Internet Explorer support (uses "URLSearchParams") +* - This is not even really a fork of the upstream version any more +* - Drops upstream requirement of "QueryString" include (URL.URLSearchParams) +* - Drops upstream requirement of "FormatDate" include (Date.toISOString()) +*/ + +URLSearchParams.prototype.getDefault = function ( name, value ) { + // Overload URLSearchParams to allow "default" values. + return ( this.get( name ) === null ) ? value : this.get( name ); +}; + +function refreshZoom( query, form, image ) { + //INIT + var qs = new URLSearchParams( query.split( "\?" )[ 1 ] ); + + init(); + + refreshImg(); + + var start_epoch = parseInt( qs.getDefault( "rst_start_epoch", form.start_epoch.value ), 10 ); + var stop_epoch = parseInt( qs.getDefault( "rst_stop_epoch", form.stop_epoch.value ), 10 ); + + var highLighter = document.getElementById( "image-overlay" ); + var gutterOffsetLeft = 66; + var highlightStartX = 0; + var clickCounter = 0; + var relativeStartX = 0; + var graph_shown_width; + var epoch_shown_start; + var epoch_shown_stop; + var eachPixelEpoch; + + form.plugin_name.onblur = refreshImg; + form.start_iso8601.onblur = majDates; + form.stop_iso8601.onblur = majDates; + form.start_epoch.onblur = function() { refreshImg(); updateStartStop(); }; + form.stop_epoch.onblur = function() { refreshImg(); updateStartStop(); }; + form.lower_limit.onblur = refreshImg; + form.upper_limit.onblur = refreshImg; + form.size_x.onblur = refreshImg; + form.size_y.onblur = refreshImg; + form.btnReset.onclick = reset; + form.btnShowDay.onclick = function() { showPeriod( 1 ); }; + form.btnShowWeek.onclick = function() { showPeriod( 2 ); }; + form.btnShowMonth.onclick = function() { showPeriod( 3 ); }; + form.btnShowYear.onclick = function() { showPeriod( 4 ); }; + form.onsubmit = function() { document.activeElement.blur(); refreshImg(); return false; }; + + // Sets the onClick handler + image.onclick = click; + + //FUNCTIONS + function init() { + form.plugin_name.value = qs.getDefault( "plugin_name", "localdomain/localhost.localdomain/if_eth0" ); + form.start_epoch.value = qs.getDefault( "start_epoch", "1236561663" ); + form.stop_epoch.value = qs.getDefault( "stop_epoch", "1237561663" ); + form.lower_limit.value = qs.getDefault( "lower_limit", "" ); + form.upper_limit.value = qs.getDefault( "upper_limit", "" ); + form.size_x.value = qs.getDefault( "size_x", "" ); + form.size_y.value = qs.getDefault( "size_y", "" ); + + updateStartStop(); + } + + function reset( event ) { + init(); + + //Can be not the initial ones in case of manual refresh + form.start_epoch.value = start_epoch; + form.stop_epoch.value = stop_epoch; + updateStartStop(); + + //Redraw + scale = refreshImg(); + + //Reset gui + clickCounter = 0; + image.onmousemove = undefined; + form.start_iso8601.disabled = false; + form.stop_iso8601.disabled = false; + form.start_epoch.disabled = false; + form.stop_epoch.disabled = false; + highLighter.style.left = "0px"; + highLighter.style.width = "2px"; + highLighter.style.display = "none"; + + document.activeElement.blur(); + return false; + } + + function refreshImg(event) { + image.src = qs.getDefault( "cgiurl_graph", "/munin-cgi/munin-cgi-graph" ) + "/" + + form.plugin_name.value + + "-pinpoint=" + parseInt( form.start_epoch.value, 10 ) + "," + parseInt( form.stop_epoch.value, 10 ) + + ".png" + "?" + + "&lower_limit=" + form.lower_limit.value + + "&upper_limit=" + form.upper_limit.value + + "&size_x=" + form.size_x.value + + "&size_y=" + form.size_y.value; + } + + function updateStartStop() { + form.start_iso8601.value = new Date( form.start_epoch.value * 1000 ).toISOString(); + form.stop_iso8601.value = new Date( form.stop_epoch.value * 1000 ).toISOString(); + } + + function majDates( event ) { + var lowLimit = new Date(), + topLimit = new Date(), + date_parsed = null; + + lowLimit.setFullYear( lowLimit.getFullYear() - 1 ); + + date_parsed = new Date( Date.parse( form.start_iso8601.value ) || lowLimit.getTime() ); + form.start_epoch.value = Math.floor( date_parsed.getTime() / 1000 ); + + date_parsed = new Date( Date.parse( form.stop_iso8601.value) || topLimit.getTime() ); + form.stop_epoch.value = Math.floor( date_parsed.getTime() / 1000 ); + + updateStartStop(); + + refreshImg(); + } + + function click( event ) { + var relativeClickX = getClickLocation( event ), + thisEpoch = null; + + switch ( ( clickCounter++ ) % 3 ) { + case 0: // First click of the displayed graph + graph_shown_width = parseInt( form.size_x.value, 10) ; + epoch_shown_start = parseInt( form.start_epoch.value,10 ); + epoch_shown_stop = parseInt( form.stop_epoch.value, 10 ); + eachPixelEpoch = ( ( epoch_shown_stop - epoch_shown_start ) / graph_shown_width ); + relativeStartX = ( relativeClickX < 0 ? 0 : relativeClickX ); + + form.start_iso8601.disabled = true; + form.stop_iso8601.disabled = true; + form.start_epoch.disabled = true; + form.stop_epoch.disabled = true; + + highlightStartX = event.pageX; + highLighter.style.left = ( relativeStartX + gutterOffsetLeft + image.offsetLeft ) + "px"; + highLighter.style.display = "block"; + + form.start_epoch.value = offsetEpoch( relativeClickX ); + updateStartStop(); + + image.onmousemove = divMouseMove; + + break; + case 1: // Second (end) click of the displayed graph + thisEpoch = offsetEpoch( relativeClickX ); + + image.onmousemove = undefined; + form.start_iso8601.disabled = false; + form.stop_iso8601.disabled = false; + form.start_epoch.disabled = false; + form.stop_epoch.disabled = false; + + // For negative values, assume we want a new start point and the old end point. + // If it's not, set it. + if ( thisEpoch > form.start_epoch.value ) { + form.stop_epoch.value = thisEpoch; + } else { + form.stop_epoch.value = Math.floor( epoch_shown_stop ); + highLighter.style.width = ( graph_shown_width - relativeStartX ) + "px"; + } + updateStartStop(); + + break; + case 2: // Nevermind or Do It. + thisEpoch = offsetEpoch( relativeClickX ); + + if ( thisEpoch >= form.start_epoch.value && thisEpoch <= form.stop_epoch.value ) { + refreshImg(); + } else { + form.start_epoch.value = epoch_shown_start; + form.stop_epoch.value = epoch_shown_stop; + updateStartStop(); + } + + highLighter.style.left = "0px"; + highLighter.style.width = "2px"; + highLighter.style.display = "none"; + } + } + + function divMouseMove( event ) { + var diff = event.pageX - highlightStartX, + maxDiff = graph_shown_width - relativeStartX, + relativeClickX = getClickLocation( event ); + + form.stop_epoch.value = offsetEpoch( relativeClickX ); + updateStartStop(); + + highLighter.style.width = ( ( diff < 2 ) ? 2 : ( diff > maxDiff ? maxDiff : diff ) ) + "px"; + } + + function offsetEpoch( clickX ) { + if ( clickX < 0 ) { return Math.floor( epoch_shown_start ); } + + if ( clickX > graph_shown_width ) { return Math.floor( epoch_shown_stop ); } + + return Math.floor( epoch_shown_start + ( clickX * eachPixelEpoch ) ); + } + + function getClickLocation( event ) { + return ( event.pageX - image.getBoundingClientRect().x - gutterOffsetLeft ); + } + + function showPeriod( period ) { + var now = new Date(), + past = new Date(); + + switch (period) { + case 1: + past.setDate( past.getDate() - 1 ); break; + case 2: + past.setDate( past.getDate() - 7 ); break; + case 3: + past.setMonth( past.getMonth() - 1 ); break; + case 4: + past.setFullYear( past.getFullYear() - 1 ); break; + } + + form.start_epoch.value = Math.floor( past.getTime() / 1000 ); + form.stop_epoch.value = Math.floor( now.getTime() / 1000 ); + + updateStartStop(); + refreshImg(); + document.activeElement.blur(); + return false; + } +} diff --git a/templates/munstrap4/templates/munin-categoryview.tmpl b/templates/muncollapse/templates/munin-categoryview.tmpl similarity index 100% rename from templates/munstrap4/templates/munin-categoryview.tmpl rename to templates/muncollapse/templates/munin-categoryview.tmpl diff --git a/templates/munstrap4/templates/munin-comparison-day.tmpl b/templates/muncollapse/templates/munin-comparison-day.tmpl similarity index 95% rename from templates/munstrap4/templates/munin-comparison-day.tmpl rename to templates/muncollapse/templates/munin-comparison-day.tmpl index aa73d181..f9c51760 100644 --- a/templates/munstrap4/templates/munin-comparison-day.tmpl +++ b/templates/muncollapse/templates/munin-comparison-day.tmpl @@ -1,9 +1,5 @@ -

Comparison: by day

- - -
diff --git a/templates/munstrap4/templates/munin-nodeview.tmpl b/templates/muncollapse/templates/munin-nodeview.tmpl similarity index 77% rename from templates/munstrap4/templates/munin-nodeview.tmpl rename to templates/muncollapse/templates/munin-nodeview.tmpl index 253589d2..a95f216e 100644 --- a/templates/munstrap4/templates/munin-nodeview.tmpl +++ b/templates/muncollapse/templates/munin-nodeview.tmpl @@ -13,84 +13,77 @@
diff --git a/templates/munstrap4/templates/munin-overview.tmpl b/templates/muncollapse/templates/munin-overview.tmpl similarity index 100% rename from templates/munstrap4/templates/munin-overview.tmpl rename to templates/muncollapse/templates/munin-overview.tmpl diff --git a/templates/munstrap4/templates/munin-problemview.tmpl b/templates/muncollapse/templates/munin-problemview.tmpl similarity index 100% rename from templates/munstrap4/templates/munin-problemview.tmpl rename to templates/muncollapse/templates/munin-problemview.tmpl diff --git a/templates/munstrap4/templates/munin-serviceview.tmpl b/templates/muncollapse/templates/munin-serviceview.tmpl similarity index 74% rename from templates/munstrap4/templates/munin-serviceview.tmpl rename to templates/muncollapse/templates/munin-serviceview.tmpl index c0f6d5ad..1bfab802 100644 --- a/templates/munstrap4/templates/munin-serviceview.tmpl +++ b/templates/muncollapse/templates/munin-serviceview.tmpl @@ -20,6 +20,7 @@
+ daily graph