Rockwells_LogViewer - Version 0.2.0

Version Notes

Added a checkbox for disabling line numbers as it can get unresponsive with larger log files. Preference is stored in a session cookie.

Download this release

Release Info

Developer Jukka Viljala
Extension Rockwells_LogViewer
Version 0.2.0
Comparing to
See all releases


Code changes from version 0.1.0 to 0.2.0

app/code/community/Rockwells/LogViewer/Block/Adminhtml/Viewer/Edit/Form.php CHANGED
@@ -8,7 +8,12 @@ class Rockwells_LogViewer_Block_Adminhtml_Viewer_Edit_Form extends Mage_Adminhtm
8
  ));
9
 
10
  $fieldset = $form->addFieldset('view_file', array());
11
-
 
 
 
 
 
12
  $textarea = $fieldset->addField('log-contents', 'textarea', array(
13
  'label' => Mage::helper('logviewer')->__('File Contents'),
14
  'name' => 'log-contents',
8
  ));
9
 
10
  $fieldset = $form->addFieldset('view_file', array());
11
+ $fieldset->addField('enable-linenumbers', 'checkbox', array(
12
+ 'label' => Mage::helper('logviewer')->__('Enable Line Numbers'),
13
+ 'name' => 'enable-linenumbers',
14
+ 'checked' => 'checked',
15
+ 'after_element_html' => '&nbsp;&nbsp;&nbsp;<label for="enable-linenumbers"><i>' . Mage::helper('logviewer')->__("Uncheck this if you're experiencing bad performance while scrolling") . '</i></label>',
16
+ ));
17
  $textarea = $fieldset->addField('log-contents', 'textarea', array(
18
  'label' => Mage::helper('logviewer')->__('File Contents'),
19
  'name' => 'log-contents',
app/code/community/Rockwells/LogViewer/controllers/Adminhtml/IndexController.php CHANGED
@@ -74,5 +74,17 @@ class Rockwells_LogViewer_Adminhtml_IndexController extends Mage_Adminhtml_Contr
74
  }
75
  $this->_redirect('*/*/');
76
  }
 
 
 
 
 
 
 
 
 
 
 
 
77
 
78
  }
74
  }
75
  $this->_redirect('*/*/');
76
  }
77
+
78
+ // public function loremAction() {
79
+ // $lorem = explode(' ', 'lorem ipsum dolor sit amet consectetur adipiscing elit donec non porta quam in placerat nulla nam malesuada massa sed eros vestibulum pellentesque consequat vitae orci nunc sollicitudin enim accumsan metus congue volutpat ut malesuada viverra diam non scelerisque sed eros ligula dignissim et iaculis vel eleifend pellentesque elit aenean at enim porttitor sodales odio eu tempus augue duis bibendum ligula ut purus auctor condimentum aliquam erat volutpat fusce et blandit neque non imperdiet nulla aliquam eros enim pellentesque vitae ultricies quis tempus ac augue suspendisse elit mi elementum sit amet nisl et rutrum pharetra sapien');
80
+ // $logs = array('exception.log', 'system.log', 'custom.log');
81
+ // foreach ($logs as $log) {
82
+ // for ($i = 0, $c = rand(50, 5000); $i < $c; $i++) {
83
+ // $len = rand(2, count($lorem));
84
+ // $text = implode(' ', array_slice($lorem, 0, $len));
85
+ // Mage::log($text, rand(0, 7), $log);
86
+ // }
87
+ // }
88
+ // }
89
 
90
  }
app/code/community/Rockwells/LogViewer/etc/config.xml CHANGED
@@ -2,7 +2,7 @@
2
  <config>
3
  <modules>
4
  <Rockwells_LogViewer>
5
- <version>0.1.0</version>
6
  </Rockwells_LogViewer>
7
  </modules>
8
  <global>
2
  <config>
3
  <modules>
4
  <Rockwells_LogViewer>
5
+ <version>0.2.0</version>
6
  </Rockwells_LogViewer>
7
  </modules>
8
  <global>
app/locale/en_US/Rockwells_LogViewer.csv CHANGED
@@ -20,4 +20,5 @@
20
  "No files selected.","No files selected."
21
  "Emptied files:<br /> * %s","Emptied files:<br /> * %s"
22
  "Could not empty files:<br /> * %s","Could not empty files:<br /> * %s"
23
- "<br /> * ","<br /> * "
 
20
  "No files selected.","No files selected."
21
  "Emptied files:<br /> * %s","Emptied files:<br /> * %s"
22
  "Could not empty files:<br /> * %s","Could not empty files:<br /> * %s"
23
+ "<br /> * ","<br /> * "
24
+ "Uncheck this if you're experiencing bad performance while scrolling","Uncheck this if you're experiencing bad performance while scrolling"
package.xml CHANGED
@@ -1,18 +1,18 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Rockwells_LogViewer</name>
4
- <version>0.1.0</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/mit-license.php">MIT License (MIT)</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Backend viewer for log files.</summary>
10
  <description>Provides way to view log files in the Magento backend. All files in the /var/log directory can be viewed and emptied if desired.</description>
11
- <notes>Initial release.</notes>
12
  <authors><author><name>Jukka Viljala</name><user>murkeli</user><email>murkelius@gmail.com</email></author></authors>
13
- <date>2015-03-13</date>
14
- <time>21:41:58</time>
15
- <contents><target name="magecommunity"><dir name="Rockwells"><dir name="LogViewer"><dir name="Block"><dir name="Adminhtml"><dir name="Viewer"><dir name="Edit"><file name="Form.php" hash="f329c2f1d50683d15c5d22a01139aba8"/></dir><file name="Grid.php" hash="6e436266633a5f0ba12953b2b65570ec"/><file name="View.php" hash="d1891de15029897f9ca307c09aad4ad7"/></dir><file name="Viewer.php" hash="f659d3b810b7f276261bdf7d07e87563"/></dir></dir><dir name="Helper"><file name="Data.php" hash="f73a99ff5af3f2863b6039c706c249f2"/></dir><dir name="controllers"><dir name="Adminhtml"><file name="IndexController.php" hash="0c90479f83c0fc4b7e6ecf8003d09bc1"/></dir></dir><dir name="etc"><file name="config.xml" hash="876ef0e98060fdfd75a02349947c209f"/></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="logviewer"><file name="logviewer.xml" hash="ed4cb78b3fbf51e9f9f30d5e72c72fe3"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Rockwells_LogViewer.xml" hash="20cefafd2c0d57a51e980a62054418be"/></dir></target><target name="magelocale"><dir name="en_US"><file name="Rockwells_LogViewer.csv" hash="beab09c3b3d0d978f5533feaf09ea4a2"/></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="logviewer"><file name="linedtextarea.css" hash="2e594409a47f046919afc51fda73440c"/><file name="linedtextarea.js" hash="074669b1ac7f01b582216011a7a043de"/><file name="load.js" hash="975098b892ed0131038978066a35c09e"/></dir></dir></dir></dir></target></contents>
16
  <compatible/>
17
  <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php><package><name>Mage_Core_Modules</name><channel>community</channel><min>1.6.0.0</min><max>1.9.1.0</max></package></required></dependencies>
18
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Rockwells_LogViewer</name>
4
+ <version>0.2.0</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/mit-license.php">MIT License (MIT)</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Backend viewer for log files.</summary>
10
  <description>Provides way to view log files in the Magento backend. All files in the /var/log directory can be viewed and emptied if desired.</description>
11
+ <notes>Added a checkbox for disabling line numbers as it can get unresponsive with larger log files. Preference is stored in a session cookie.</notes>
12
  <authors><author><name>Jukka Viljala</name><user>murkeli</user><email>murkelius@gmail.com</email></author></authors>
13
+ <date>2015-04-01</date>
14
+ <time>13:43:45</time>
15
+ <contents><target name="magecommunity"><dir name="Rockwells"><dir name="LogViewer"><dir name="Block"><dir name="Adminhtml"><dir name="Viewer"><dir name="Edit"><file name="Form.php" hash="83b75d1c46553aad46aa9dc824d5a0ea"/></dir><file name="Grid.php" hash="6e436266633a5f0ba12953b2b65570ec"/><file name="View.php" hash="d1891de15029897f9ca307c09aad4ad7"/></dir><file name="Viewer.php" hash="f659d3b810b7f276261bdf7d07e87563"/></dir></dir><dir name="Helper"><file name="Data.php" hash="f73a99ff5af3f2863b6039c706c249f2"/></dir><dir name="controllers"><dir name="Adminhtml"><file name="IndexController.php" hash="7de85dcbf4d5f5ab94e17d2d0976d10b"/></dir></dir><dir name="etc"><file name="config.xml" hash="eb14c8933204cabd849ab94416150a79"/></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="logviewer"><file name="logviewer.xml" hash="ed4cb78b3fbf51e9f9f30d5e72c72fe3"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Rockwells_LogViewer.xml" hash="20cefafd2c0d57a51e980a62054418be"/></dir></target><target name="magelocale"><dir name="en_US"><file name="Rockwells_LogViewer.csv" hash="a58d6f48042a0065a2e66c5ec0106d6d"/></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="logviewer"><file name="linedtextarea.css" hash="2e594409a47f046919afc51fda73440c"/><file name="linedtextarea.js" hash="6bd94134793aa8cce669dcf4f6972838"/><file name="load.js" hash="f9fa6054c632c4365a7cbcc3adfb70a0"/></dir></dir></dir></dir></target></contents>
16
  <compatible/>
17
  <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php><package><name>Mage_Core_Modules</name><channel>community</channel><min>1.6.0.0</min><max>1.9.1.0</max></package></required></dependencies>
18
  </package>
skin/adminhtml/default/default/logviewer/linedtextarea.js CHANGED
@@ -11,9 +11,11 @@
11
  */
12
  (function() {
13
 
14
- /*
15
  * Helper function to make sure the line numbers are always
16
  * kept up to the current system
 
 
17
  */
18
  var fillOutLines = function(codeLines, h, lineNo) {
19
  while ((codeLines.measure("height") - h) <= 0) {
@@ -23,78 +25,107 @@
23
  return lineNo;
24
  };
25
 
26
- var LinedTextarea = {
27
- linedtextarea: function(element) {
28
- element = $(element);
29
- var lineNo = 1;
30
- /* Turn off the wrapping of as we don't want to screw up the line numbers */
31
- element.writeAttribute("wrap", "off");
32
- element.setStyle({resize: "none"});
33
- var originalTextAreaWidth = element.measure("border-box-width");
34
-
35
- /* Wrap the text area in the elements we need */
36
- Element.wrap(element, "div", { 'class': "linedtextarea" });
37
- var linedTextAreaDiv = element.up().wrap("div", {
38
- 'class': "linedwrap",
39
- style: "width:" + originalTextAreaWidth + "px",
40
  });
41
- var linedWrapDiv = linedTextAreaDiv.up();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
- var linesDiv = new Element("div", {
44
- 'class': "lines",
45
- style: "width:50px;height:" + (element.measure("height") + 6) + "px;",
46
- });
47
- var codeLinesDiv = new Element("div", { 'class': "codelines" });
48
- linesDiv.insert(codeLinesDiv);
49
-
50
- linedTextAreaDiv.insert({ top: linesDiv });
51
-
52
- /* Draw the number bar; filling it out where necessary */
53
- lineNo = fillOutLines(codeLinesDiv, linesDiv.measure("height"), 1);
54
 
55
- /* Set the width */
56
- var sidebarWidth = linesDiv.measure("border-box-width");
57
- var paddingHorizontal = linedWrapDiv.measure("border-left") +
58
- linedWrapDiv.measure("border-right") +
59
- linedWrapDiv.measure("padding-left") +
60
- linedWrapDiv.measure("padding-right");
61
- var linedWrapDivNewWidth = originalTextAreaWidth - paddingHorizontal;
62
- var textareaNewWidth = originalTextAreaWidth - sidebarWidth - paddingHorizontal - 20;
63
 
64
- element.setStyle({ width: textareaNewWidth + "px" });
65
- linedWrapDiv.setStyle({ width: linedWrapDivNewWidth + "px" });
66
-
67
- /* React to the scroll event */
68
- element.observe("scroll", function() {
69
- //var domTextArea = $(this)[0];
70
- var scrollTop = element.scrollTop;
71
- var clientHeight = element.clientHeight;
72
- codeLinesDiv.setStyle({'margin-top': (-1 * scrollTop) + "px"});
73
- lineNo = fillOutLines(codeLinesDiv, scrollTop + clientHeight, lineNo);
74
- });
75
 
76
- /* Should the textarea get resized outside of our control */
77
- element.observe("resize", function() {
78
- linesDiv.height(element.clientHeight + 6);
79
- });
80
-
81
- var selectionChange = function() {
82
- if (element.selectionStart !== undefined && element.selectionStart >= 0) {
83
- var start = element.selectionStart;
84
- var end = element.selectionEnd;
85
- var firstLine = element.value.substr(0, start).split("\n").length;
86
- var lastLine = firstLine + element.value.substr(start, end - start).split("\n").length;
87
- $$(".lineselect").each(function(elem) {
88
- elem.removeClassName("lineselect");
89
- });
90
- for (var line = firstLine; line < lastLine; line++) {
91
- $("lineno-" + line).addClassName("lineselect");
92
- }
93
- }
94
- };
95
- element.observe("keyup", selectionChange);
96
- element.observe("click", selectionChange);
97
- element.observe("focus", selectionChange);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  },
99
  };
100
 
11
  */
12
  (function() {
13
 
14
+ /**
15
  * Helper function to make sure the line numbers are always
16
  * kept up to the current system
17
+ *
18
+ * @returns current line number
19
  */
20
  var fillOutLines = function(codeLines, h, lineNo) {
21
  while ((codeLines.measure("height") - h) <= 0) {
25
  return lineNo;
26
  };
27
 
28
+ /**
29
+ * Highlights the current selected row number
30
+ */
31
+ var selectionChange = function() {
32
+ if (this.selectionStart !== undefined && this.selectionStart >= 0) {
33
+ var start = this.selectionStart;
34
+ var end = this.selectionEnd;
35
+ var firstLine = this.value.substr(0, start).split("\n").length;
36
+ var lastLine = firstLine + this.value.substr(start, end - start).split("\n").length;
37
+ $$(".lineselect").each(function(elem) {
38
+ elem.removeClassName("lineselect");
 
 
 
39
  });
40
+ for (var line = firstLine; line < lastLine; line++) {
41
+ $("lineno-" + line).addClassName("lineselect");
42
+ }
43
+ }
44
+ };
45
+
46
+ var construct = function(element) {
47
+ /* Preserve current scroll */
48
+ var currentScroll = element.scrollTop;
49
+ /* Store original style to support destruction */
50
+ element.origStyle = element.getAttribute("style");
51
+
52
+ var lineNo = 1;
53
+ /* Turn off the wrapping of as we don't want to screw up the line numbers */
54
+ element.writeAttribute("wrap", "off");
55
+ element.setStyle({resize: "none"});
56
+ var originalTextAreaWidth = element.measure("border-box-width");
57
 
58
+ /* Wrap the text area in the elements we need */
59
+ Element.wrap(element, "div", { 'class': "linedtextarea" });
60
+ var linedTextAreaDiv = element.up().wrap("div", {
61
+ 'class': "linedwrap",
62
+ style: "width:" + originalTextAreaWidth + "px",
63
+ });
 
 
 
 
 
64
 
65
+ var linesDiv = new Element("div", {
66
+ 'class': "lines",
67
+ style: "width:50px;height:" + (element.measure("height") + 6) + "px;",
68
+ });
69
+ var codeLinesDiv = new Element("div", { 'class': "codelines" });
70
+ linesDiv.insert(codeLinesDiv);
 
 
71
 
72
+ linedTextAreaDiv.insert({ top: linesDiv });
 
 
 
 
 
 
 
 
 
 
73
 
74
+ /* Draw the number bar; filling it out where necessary */
75
+ lineNo = fillOutLines(codeLinesDiv, linesDiv.measure("height"), lineNo);
76
+
77
+ /* Set the width */
78
+ var sidebarWidth = linesDiv.measure("border-box-width");
79
+ var paddingHorizontal = linedTextAreaDiv.measure("border-left") +
80
+ linedTextAreaDiv.measure("border-right") +
81
+ linedTextAreaDiv.measure("padding-left") +
82
+ linedTextAreaDiv.measure("padding-right");
83
+ var textareaNewWidth = originalTextAreaWidth - sidebarWidth - paddingHorizontal - 20;
84
+
85
+ element.setStyle({ width: textareaNewWidth + "px" });
86
+
87
+ /* React to the scroll event */
88
+ element.observe("scroll", function() {
89
+ var scrollTop = element.scrollTop;
90
+ var clientHeight = element.clientHeight;
91
+ codeLinesDiv.setStyle({'margin-top': (-1 * scrollTop) + "px"});
92
+ lineNo = fillOutLines(codeLinesDiv, scrollTop + clientHeight, lineNo);
93
+ });
94
+
95
+ /* Should the textarea get resized outside of our control */
96
+ element.observe("resize", function() {
97
+ linesDiv.height(element.clientHeight + 6);
98
+ });
99
+
100
+ element.observe("keyup", selectionChange);
101
+ element.observe("click", selectionChange);
102
+ element.observe("focus", selectionChange);
103
+
104
+ element.scrollTop = currentScroll;
105
+ };
106
+
107
+ var destroy = function(element) {
108
+ var currentScroll = element.scrollTop;
109
+ /* Remove events */
110
+ element.stopObserving();
111
+ /* Reset style */
112
+ element.setAttribute("style", element.origStyle);
113
+ /* Move element out of our divs and destroy them */
114
+ var linedWrap = document.getElementsByClassName("linedwrap")[0];
115
+ linedWrap.parentNode.appendChild(element);
116
+ linedWrap.remove();
117
+ /* Preserve scroll */
118
+ element.scrollTop = currentScroll;
119
+ };
120
+
121
+ var LinedTextarea = {
122
+ linedtextarea: function(element, command) {
123
+ element = $(element);
124
+ if (command == "destroy") {
125
+ destroy(element);
126
+ } else {
127
+ construct(element);
128
+ }
129
  },
130
  };
131
 
skin/adminhtml/default/default/logviewer/load.js CHANGED
@@ -1,4 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
 
2
  document.observe("dom:loaded", function(){
3
- $("log-contents").linedtextarea();
4
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*\
2
+ |*|
3
+ |*| :: cookies.js ::
4
+ |*|
5
+ |*| A complete cookies reader/writer framework with full unicode support.
6
+ |*|
7
+ |*| Revision #1 - September 4, 2014
8
+ |*|
9
+ |*| https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
10
+ |*| https://developer.mozilla.org/User:fusionchess
11
+ |*|
12
+ |*| This framework is released under the GNU Public License, version 3 or later.
13
+ |*| http://www.gnu.org/licenses/gpl-3.0-standalone.html
14
+ |*|
15
+ |*| Syntaxes:
16
+ |*|
17
+ |*| * docCookies.setItem(name, value[, end[, path[, domain[, secure]]]])
18
+ |*| * docCookies.getItem(name)
19
+ |*| * docCookies.removeItem(name[, path[, domain]])
20
+ |*| * docCookies.hasItem(name)
21
+ |*| * docCookies.keys()
22
+ |*|
23
+ \*/
24
+
25
+ var docCookies = {
26
+ getItem: function (sKey) {
27
+ if (!sKey) { return null; }
28
+ return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
29
+ },
30
+ setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
31
+ if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
32
+ var sExpires = "";
33
+ if (vEnd) {
34
+ switch (vEnd.constructor) {
35
+ case Number:
36
+ sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
37
+ break;
38
+ case String:
39
+ sExpires = "; expires=" + vEnd;
40
+ break;
41
+ case Date:
42
+ sExpires = "; expires=" + vEnd.toUTCString();
43
+ break;
44
+ }
45
+ }
46
+ document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
47
+ return true;
48
+ },
49
+ removeItem: function (sKey, sPath, sDomain) {
50
+ if (!this.hasItem(sKey)) { return false; }
51
+ document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "");
52
+ return true;
53
+ },
54
+ hasItem: function (sKey) {
55
+ if (!sKey) { return false; }
56
+ return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
57
+ },
58
+ keys: function () {
59
+ var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
60
+ for (var nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); }
61
+ return aKeys;
62
+ }
63
+ };
64
 
65
  document.observe("dom:loaded", function(){
66
+ var checked = docCookies.getItem("linenumbers");
67
+ if (checked == 'false') {
68
+ checked = 0;
69
+ } else {
70
+ checked = 1;
71
+ }
72
+ $("enable-linenumbers").checked = checked;
73
+
74
+ if ($("enable-linenumbers").checked) {
75
+ $("log-contents").linedtextarea();
76
+ }
77
+
78
+ $("enable-linenumbers").observe("change", function() {
79
+ docCookies.setItem("linenumbers", this.checked, null, "/");
80
+ if (this.checked) {
81
+ $("log-contents").linedtextarea();
82
+ } else {
83
+ $("log-contents").linedtextarea("destroy");
84
+ }
85
+ });
86
+ });