logster 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +18 -18
  3. data/.travis.yml +15 -15
  4. data/CHANGELOG.md +137 -130
  5. data/Gemfile +4 -4
  6. data/Guardfile +8 -8
  7. data/LICENSE.txt +22 -22
  8. data/README.md +99 -99
  9. data/Rakefile +24 -24
  10. data/assets/fonts/FontAwesome.otf +0 -0
  11. data/assets/fonts/fontawesome-webfont.eot +0 -0
  12. data/assets/fonts/fontawesome-webfont.svg +639 -639
  13. data/assets/fonts/fontawesome-webfont.ttf +0 -0
  14. data/assets/fonts/fontawesome-webfont.woff +0 -0
  15. data/assets/fonts/fontawesome-webfont.woff2 +0 -0
  16. data/assets/images/Icon-144_rounded.png +0 -0
  17. data/assets/images/Icon-144_square.png +0 -0
  18. data/assets/images/icon_144x144.png +0 -0
  19. data/assets/images/icon_64x64.png +0 -0
  20. data/assets/javascript/client-app.js +81 -81
  21. data/assets/javascript/vendor.js +5302 -5302
  22. data/assets/stylesheets/client-app.css +0 -0
  23. data/assets/stylesheets/vendor.css +3 -3
  24. data/build_client_app.sh +12 -12
  25. data/client-app/.editorconfig +20 -20
  26. data/client-app/.ember-cli +9 -9
  27. data/client-app/.eslintignore +19 -19
  28. data/client-app/.eslintrc.js +46 -46
  29. data/client-app/.gitignore +23 -23
  30. data/client-app/.travis.yml +27 -27
  31. data/client-app/.watchmanconfig +3 -3
  32. data/client-app/README.md +57 -57
  33. data/client-app/app/app.js +14 -14
  34. data/client-app/app/components/message-info.js +18 -18
  35. data/client-app/app/components/message-row.js +45 -45
  36. data/client-app/app/components/panel-resizer.js +75 -75
  37. data/client-app/app/components/tab-contents.js +27 -27
  38. data/client-app/app/components/tab-link.js +5 -5
  39. data/client-app/app/components/tabbed-section.js +32 -32
  40. data/client-app/app/components/time-formatter.js +25 -25
  41. data/client-app/app/components/update-time.js +21 -21
  42. data/client-app/app/controllers/index.js +83 -83
  43. data/client-app/app/controllers/show.js +13 -13
  44. data/client-app/app/index.html +29 -29
  45. data/client-app/app/initializers/app-init.js +55 -55
  46. data/client-app/app/lib/preload.js +14 -14
  47. data/client-app/app/lib/utilities.js +140 -140
  48. data/client-app/app/models/message-collection.js +158 -158
  49. data/client-app/app/models/message.js +99 -99
  50. data/client-app/app/resolver.js +3 -3
  51. data/client-app/app/router.js +14 -14
  52. data/client-app/app/routes/index.js +53 -53
  53. data/client-app/app/routes/show.js +14 -14
  54. data/client-app/app/styles/app.css +387 -387
  55. data/client-app/app/templates/application.hbs +2 -2
  56. data/client-app/app/templates/components/message-info.hbs +44 -44
  57. data/client-app/app/templates/components/message-row.hbs +17 -17
  58. data/client-app/app/templates/components/tabbed-section.hbs +10 -10
  59. data/client-app/app/templates/components/time-formatter.hbs +1 -1
  60. data/client-app/app/templates/index.hbs +57 -57
  61. data/client-app/app/templates/show.hbs +4 -4
  62. data/client-app/config/environment.js +51 -51
  63. data/client-app/config/optional-features.json +3 -3
  64. data/client-app/config/targets.js +18 -18
  65. data/client-app/ember-cli-build.js +29 -29
  66. data/client-app/package-lock.json +11365 -11365
  67. data/client-app/package.json +56 -56
  68. data/client-app/testem.js +25 -25
  69. data/client-app/tests/index.html +34 -34
  70. data/client-app/tests/integration/components/message-info-test.js +26 -26
  71. data/client-app/tests/integration/components/message-row-test.js +26 -26
  72. data/client-app/tests/integration/components/panel-resizer-test.js +26 -26
  73. data/client-app/tests/integration/components/tab-contents-test.js +26 -26
  74. data/client-app/tests/integration/components/tab-link-test.js +26 -26
  75. data/client-app/tests/integration/components/tabbed-section-test.js +26 -26
  76. data/client-app/tests/integration/components/time-formatter-test.js +26 -26
  77. data/client-app/tests/integration/components/update-time-test.js +26 -26
  78. data/client-app/tests/test-helper.js +8 -8
  79. data/client-app/tests/unit/controllers/index-test.js +12 -12
  80. data/client-app/tests/unit/controllers/show-test.js +12 -12
  81. data/client-app/tests/unit/initializers/app-init-test.js +31 -31
  82. data/client-app/tests/unit/routes/index-test.js +11 -11
  83. data/client-app/tests/unit/routes/show-test.js +11 -11
  84. data/lib/examples/sidekiq_logster_reporter.rb +21 -21
  85. data/lib/logster.rb +54 -54
  86. data/lib/logster/base_store.rb +130 -130
  87. data/lib/logster/configuration.rb +25 -25
  88. data/lib/logster/ignore_pattern.rb +65 -65
  89. data/lib/logster/logger.rb +108 -102
  90. data/lib/logster/message.rb +227 -227
  91. data/lib/logster/middleware/debug_exceptions.rb +26 -26
  92. data/lib/logster/middleware/reporter.rb +56 -56
  93. data/lib/logster/middleware/viewer.rb +220 -220
  94. data/lib/logster/rails/railtie.rb +58 -58
  95. data/lib/logster/redis_store.rb +481 -481
  96. data/lib/logster/version.rb +3 -3
  97. data/lib/logster/web.rb +14 -14
  98. data/logster.gemspec +34 -34
  99. data/test/examples/test_sidekiq_reporter_example.rb +46 -46
  100. data/test/fake_data/Gemfile +4 -4
  101. data/test/fake_data/generate.rb +10 -10
  102. data/test/logster/middleware/test_reporter.rb +21 -21
  103. data/test/logster/middleware/test_viewer.rb +96 -96
  104. data/test/logster/test_base_store.rb +147 -147
  105. data/test/logster/test_ignore_pattern.rb +41 -41
  106. data/test/logster/test_logger.rb +80 -74
  107. data/test/logster/test_message.rb +34 -34
  108. data/test/logster/test_redis_rate_limiter.rb +230 -230
  109. data/test/logster/test_redis_store.rb +427 -427
  110. data/test/test_helper.rb +38 -38
  111. data/vendor/assets/javascripts/logster.js.erb +39 -39
  112. metadata +3 -3
@@ -1,21 +1,21 @@
1
- import Component from "@ember/component";
2
- import { formatTime } from "client-app/lib/utilities";
3
-
4
- export default Component.extend({
5
- didInsertElement() {
6
- const updateTimes = () => {
7
- Em.$(".auto-update-time").each(function() {
8
- const timestamp = parseInt(this.getAttribute("data-timestamp"), 10);
9
- const elem = this;
10
- const text = formatTime(timestamp);
11
-
12
- if (text !== elem.innerText) {
13
- elem.innerText = text;
14
- }
15
- });
16
- Em.run.later(updateTimes, 60000);
17
- };
18
-
19
- Em.run.later(updateTimes, 60000);
20
- }
21
- });
1
+ import Component from "@ember/component";
2
+ import { formatTime } from "client-app/lib/utilities";
3
+
4
+ export default Component.extend({
5
+ didInsertElement() {
6
+ const updateTimes = () => {
7
+ Em.$(".auto-update-time").each(function() {
8
+ const timestamp = parseInt(this.getAttribute("data-timestamp"), 10);
9
+ const elem = this;
10
+ const text = formatTime(timestamp);
11
+
12
+ if (text !== elem.innerText) {
13
+ elem.innerText = text;
14
+ }
15
+ });
16
+ Em.run.later(updateTimes, 60000);
17
+ };
18
+
19
+ Em.run.later(updateTimes, 60000);
20
+ }
21
+ });
@@ -1,83 +1,83 @@
1
- import Controller from "@ember/controller";
2
- import { ajax } from "client-app/lib/utilities";
3
- import { observer } from "@ember/object";
4
-
5
- export default Controller.extend({
6
- currentMessage: Em.computed.alias("model.currentMessage"),
7
-
8
- actions: {
9
- expandMessage(message) {
10
- message.expand();
11
- },
12
-
13
- selectMessage(message) {
14
- const old = this.get("currentMessage");
15
- if (old) {
16
- old.set("selected", false);
17
- }
18
-
19
- message.set("selected", true);
20
- this.set("currentMessage", message);
21
- },
22
-
23
- showMoreBefore() {
24
- this.get("model").showMoreBefore();
25
- },
26
-
27
- loadMore() {
28
- return this.get("model").loadMore();
29
- },
30
-
31
- clear() {
32
- if (confirm("Clear the logs?\n\nCancel = No, OK = Clear")) {
33
- ajax("/clear", { type: "POST" }).then(() => {
34
- this.get("model").reload();
35
- });
36
- }
37
- },
38
-
39
- removeMessage(msg) {
40
- const messages = this.get("model");
41
- messages.destroy(msg);
42
- },
43
-
44
- solveMessage(msg) {
45
- const messages = this.get("model");
46
- messages.solve(msg);
47
- }
48
- },
49
-
50
- filterChanged: observer(
51
- "showDebug",
52
- "showInfo",
53
- "showWarn",
54
- "showErr",
55
- "showFatal",
56
- function() {
57
- const filter = [];
58
- ["Debug", "Info", "Warn", "Err", "Fatal"].forEach((severity, index) => {
59
- if (this.get(`show${severity}`)) {
60
- filter.push(index);
61
- }
62
- });
63
-
64
- // always show unknown, rare
65
- filter.push(5);
66
- const model = this.get("model");
67
- model.set("filter", filter);
68
- if (this.get("initialized")) {
69
- model.reload();
70
- }
71
- }
72
- ),
73
-
74
- searchChanged: observer("search", function() {
75
- const search = this.get("search");
76
- const model = this.get("model");
77
- model.set("search", search);
78
-
79
- if (this.get("initialized")) {
80
- model.reload();
81
- }
82
- })
83
- });
1
+ import Controller from "@ember/controller";
2
+ import { ajax } from "client-app/lib/utilities";
3
+ import { observer } from "@ember/object";
4
+
5
+ export default Controller.extend({
6
+ currentMessage: Em.computed.alias("model.currentMessage"),
7
+
8
+ actions: {
9
+ expandMessage(message) {
10
+ message.expand();
11
+ },
12
+
13
+ selectMessage(message) {
14
+ const old = this.get("currentMessage");
15
+ if (old) {
16
+ old.set("selected", false);
17
+ }
18
+
19
+ message.set("selected", true);
20
+ this.set("currentMessage", message);
21
+ },
22
+
23
+ showMoreBefore() {
24
+ this.get("model").showMoreBefore();
25
+ },
26
+
27
+ loadMore() {
28
+ return this.get("model").loadMore();
29
+ },
30
+
31
+ clear() {
32
+ if (confirm("Clear the logs?\n\nCancel = No, OK = Clear")) {
33
+ ajax("/clear", { type: "POST" }).then(() => {
34
+ this.get("model").reload();
35
+ });
36
+ }
37
+ },
38
+
39
+ removeMessage(msg) {
40
+ const messages = this.get("model");
41
+ messages.destroy(msg);
42
+ },
43
+
44
+ solveMessage(msg) {
45
+ const messages = this.get("model");
46
+ messages.solve(msg);
47
+ }
48
+ },
49
+
50
+ filterChanged: observer(
51
+ "showDebug",
52
+ "showInfo",
53
+ "showWarn",
54
+ "showErr",
55
+ "showFatal",
56
+ function() {
57
+ const filter = [];
58
+ ["Debug", "Info", "Warn", "Err", "Fatal"].forEach((severity, index) => {
59
+ if (this.get(`show${severity}`)) {
60
+ filter.push(index);
61
+ }
62
+ });
63
+
64
+ // always show unknown, rare
65
+ filter.push(5);
66
+ const model = this.get("model");
67
+ model.set("filter", filter);
68
+ if (this.get("initialized")) {
69
+ model.reload();
70
+ }
71
+ }
72
+ ),
73
+
74
+ searchChanged: observer("search", function() {
75
+ const search = this.get("search");
76
+ const model = this.get("model");
77
+ model.set("search", search);
78
+
79
+ if (this.get("initialized")) {
80
+ model.reload();
81
+ }
82
+ })
83
+ });
@@ -1,13 +1,13 @@
1
- import Controller from "@ember/controller";
2
-
3
- export default Controller.extend({
4
- actions: {
5
- protect() {
6
- this.get("model").protect();
7
- },
8
-
9
- unprotect() {
10
- this.get("model").unprotect();
11
- }
12
- }
13
- });
1
+ import Controller from "@ember/controller";
2
+
3
+ export default Controller.extend({
4
+ actions: {
5
+ protect() {
6
+ this.get("model").protect();
7
+ },
8
+
9
+ unprotect() {
10
+ this.get("model").unprotect();
11
+ }
12
+ }
13
+ });
@@ -1,29 +1,29 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8">
5
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
- <title>ClientApp</title>
7
- <meta name="description" content="">
8
- <meta name="viewport" content="width=device-width, initial-scale=1">
9
- <meta id="preloaded-data" data-root-path="/logs" data-preloaded="{}">
10
-
11
- {{content-for "head"}}
12
-
13
- <link integrity="" rel="stylesheet" href="{{rootURL}}assets/vendor.css">
14
- <link integrity="" rel="stylesheet" href="{{rootURL}}assets/client-app.css">
15
-
16
- <link href='//fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
17
- <link href='//fonts.googleapis.com/css?family=Roboto+Mono' rel='stylesheet' type='text/css'>
18
-
19
- {{content-for "head-footer"}}
20
- </head>
21
- <body>
22
- {{content-for "body"}}
23
-
24
- <script src="{{rootURL}}assets/vendor.js"></script>
25
- <script src="{{rootURL}}assets/client-app.js"></script>
26
-
27
- {{content-for "body-footer"}}
28
- </body>
29
- </html>
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <title>ClientApp</title>
7
+ <meta name="description" content="">
8
+ <meta name="viewport" content="width=device-width, initial-scale=1">
9
+ <meta id="preloaded-data" data-root-path="/logs" data-preloaded="{}">
10
+
11
+ {{content-for "head"}}
12
+
13
+ <link integrity="" rel="stylesheet" href="{{rootURL}}assets/vendor.css">
14
+ <link integrity="" rel="stylesheet" href="{{rootURL}}assets/client-app.css">
15
+
16
+ <link href='//fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
17
+ <link href='//fonts.googleapis.com/css?family=Roboto+Mono' rel='stylesheet' type='text/css'>
18
+
19
+ {{content-for "head-footer"}}
20
+ </head>
21
+ <body>
22
+ {{content-for "body"}}
23
+
24
+ <script src="{{rootURL}}assets/vendor.js"></script>
25
+ <script src="{{rootURL}}assets/client-app.js"></script>
26
+
27
+ {{content-for "body-footer"}}
28
+ </body>
29
+ </html>
@@ -1,55 +1,55 @@
1
- import {
2
- updateHiddenProperty,
3
- resetTitleCount
4
- } from "client-app/lib/utilities";
5
- import { init } from "client-app/lib/preload";
6
-
7
- export function initialize() {
8
- // config for moment.js
9
- moment.updateLocale("en", {
10
- relativeTime: {
11
- future: "in %s",
12
- past: "%s ago",
13
- s: "secs",
14
- m: "a min",
15
- mm: "%d mins",
16
- h: "an hr",
17
- hh: "%d hrs",
18
- d: "a day",
19
- dd: "%d days",
20
- M: "a mth",
21
- MM: "%d mths",
22
- y: "a yr",
23
- yy: "%d yrs"
24
- }
25
- });
26
-
27
- // parse preloaded json
28
- const dataset = document.getElementById("preloaded-data").dataset;
29
- init(dataset);
30
-
31
- // setup event for updating document title and title count
32
- let hiddenProperty;
33
- let visibilitychange;
34
-
35
- ["", "webkit", "ms", "moz", "ms"].forEach(prefix => {
36
- const check = prefix + (prefix === "" ? "hidden" : "Hidden");
37
- if (document[check] !== undefined && !hiddenProperty) {
38
- hiddenProperty = check;
39
- visibilitychange = prefix + "visibilitychange";
40
- }
41
- });
42
-
43
- updateHiddenProperty(hiddenProperty);
44
- document.addEventListener(
45
- visibilitychange,
46
- () => {
47
- resetTitleCount();
48
- },
49
- false
50
- );
51
- }
52
-
53
- export default {
54
- initialize
55
- };
1
+ import {
2
+ updateHiddenProperty,
3
+ resetTitleCount
4
+ } from "client-app/lib/utilities";
5
+ import { init } from "client-app/lib/preload";
6
+
7
+ export function initialize() {
8
+ // config for moment.js
9
+ moment.updateLocale("en", {
10
+ relativeTime: {
11
+ future: "in %s",
12
+ past: "%s ago",
13
+ s: "secs",
14
+ m: "a min",
15
+ mm: "%d mins",
16
+ h: "an hr",
17
+ hh: "%d hrs",
18
+ d: "a day",
19
+ dd: "%d days",
20
+ M: "a mth",
21
+ MM: "%d mths",
22
+ y: "a yr",
23
+ yy: "%d yrs"
24
+ }
25
+ });
26
+
27
+ // parse preloaded json
28
+ const dataset = document.getElementById("preloaded-data").dataset;
29
+ init(dataset);
30
+
31
+ // setup event for updating document title and title count
32
+ let hiddenProperty;
33
+ let visibilitychange;
34
+
35
+ ["", "webkit", "ms", "moz", "ms"].forEach(prefix => {
36
+ const check = prefix + (prefix === "" ? "hidden" : "Hidden");
37
+ if (document[check] !== undefined && !hiddenProperty) {
38
+ hiddenProperty = check;
39
+ visibilitychange = prefix + "visibilitychange";
40
+ }
41
+ });
42
+
43
+ updateHiddenProperty(hiddenProperty);
44
+ document.addEventListener(
45
+ visibilitychange,
46
+ () => {
47
+ resetTitleCount();
48
+ },
49
+ false
50
+ );
51
+ }
52
+
53
+ export default {
54
+ initialize
55
+ };
@@ -1,14 +1,14 @@
1
- let CONTAINER;
2
-
3
- export function init(dataset) {
4
- CONTAINER = {
5
- rootPath: dataset.rootPath,
6
- preload: JSON.parse(dataset.preloaded)
7
- };
8
- }
9
-
10
- export default {
11
- get(key) {
12
- return Em.get(CONTAINER, key);
13
- }
14
- };
1
+ let CONTAINER;
2
+
3
+ export function init(dataset) {
4
+ CONTAINER = {
5
+ rootPath: dataset.rootPath,
6
+ preload: JSON.parse(dataset.preloaded)
7
+ };
8
+ }
9
+
10
+ export default {
11
+ get(key) {
12
+ return Em.get(CONTAINER, key);
13
+ }
14
+ };
@@ -1,140 +1,140 @@
1
- import Preload from "client-app/lib/preload";
2
-
3
- const entityMap = {
4
- "&": "&amp;",
5
- "<": "&lt;",
6
- ">": "&gt;",
7
- '"': "&quot;",
8
- "'": "&#39;",
9
- "/": "&#x2F;"
10
- };
11
-
12
- export function escapeHtml(string) {
13
- return String(string).replace(/[&<>"'/]/g, s => entityMap[s]);
14
- }
15
-
16
- export function ajax(url, settings) {
17
- settings = settings || {};
18
- settings.headers = settings.headers || {};
19
- settings.headers["X-SILENCE-LOGGER"] = true;
20
- return Em.$.ajax(Preload.get("rootPath") + url, settings);
21
- }
22
-
23
- export function preloadOrAjax(url, settings) {
24
- const preloaded = Preload.get(`preload.${url.replace(".json", "")}`);
25
- if (preloaded) {
26
- return Em.RSVP.resolve(preloaded);
27
- } else {
28
- return ajax(url, settings);
29
- }
30
- }
31
-
32
- let HIDDEN_PROPERTY;
33
- let TITLE;
34
- let TITLE_COUNT;
35
-
36
- export function updateHiddenProperty(property) {
37
- HIDDEN_PROPERTY = property;
38
- }
39
-
40
- export function isHidden() {
41
- if (HIDDEN_PROPERTY !== undefined) {
42
- return document[HIDDEN_PROPERTY];
43
- } else {
44
- return !document.hasFocus;
45
- }
46
- }
47
-
48
- export function increaseTitleCount(increment) {
49
- if (!isHidden()) {
50
- return;
51
- }
52
- TITLE = TITLE || document.title;
53
- TITLE_COUNT = TITLE_COUNT || 0;
54
- TITLE_COUNT += increment;
55
- document.title = `${TITLE} (${TITLE_COUNT})`;
56
- }
57
-
58
- export function resetTitleCount() {
59
- TITLE_COUNT = 0;
60
- document.title = TITLE || document.title;
61
- }
62
-
63
- export function formatTime(timestamp) {
64
- let formatted;
65
- const time = moment(timestamp);
66
- const now = moment();
67
-
68
- if (time.diff(now.startOf("day")) > 0) {
69
- formatted = time.format("h:mm a");
70
- } else {
71
- if (time.diff(now.startOf("week")) > 0) {
72
- formatted = time.format("dd h:mm a");
73
- } else {
74
- if (time.diff(now.startOf("year")) > 0) {
75
- formatted = time.format("D MMM h:mm a");
76
- } else {
77
- formatted = time.format("D MMM YY");
78
- }
79
- }
80
- }
81
-
82
- return formatted;
83
- }
84
-
85
- export function buildArrayString(array) {
86
- const buffer = [];
87
- array.forEach(v => {
88
- if (v === null) {
89
- buffer.push("null");
90
- } else if (Object.prototype.toString.call(v) === "[object Array]") {
91
- buffer.push(buildArrayString(v));
92
- } else {
93
- buffer.push(escapeHtml(v.toString()));
94
- }
95
- });
96
- return "[" + buffer.join(", ") + "]";
97
- }
98
-
99
- export function buildHashString(hash, recurse) {
100
- if (!hash) return "";
101
-
102
- const buffer = [];
103
- const hashes = [];
104
- _.each(hash, (v, k) => {
105
- if (v === null) {
106
- buffer.push("null");
107
- } else if (Object.prototype.toString.call(v) === "[object Array]") {
108
- buffer.push(
109
- "<tr><td>" +
110
- escapeHtml(k) +
111
- "</td><td>" +
112
- buildArrayString(v) +
113
- "</td></tr>"
114
- );
115
- } else if (typeof v === "object") {
116
- hashes.push(k);
117
- } else {
118
- buffer.push(
119
- "<tr><td>" + escapeHtml(k) + "</td><td>" + escapeHtml(v) + "</td></tr>"
120
- );
121
- }
122
- });
123
-
124
- if (_.size(hashes) > 0) {
125
- _.each(hashes, function(k1) {
126
- const v = hash[k1];
127
- buffer.push("<tr><td></td><td><table>");
128
- buffer.push(
129
- "<td>" +
130
- escapeHtml(k1) +
131
- "</td><td>" +
132
- buildHashString(v, true) +
133
- "</td>"
134
- );
135
- buffer.push("</table></td></tr>");
136
- });
137
- }
138
- const className = recurse ? "" : "env-table";
139
- return "<table class='" + className + "'>" + buffer.join("\n") + "</table>";
140
- }
1
+ import Preload from "client-app/lib/preload";
2
+
3
+ const entityMap = {
4
+ "&": "&amp;",
5
+ "<": "&lt;",
6
+ ">": "&gt;",
7
+ '"': "&quot;",
8
+ "'": "&#39;",
9
+ "/": "&#x2F;"
10
+ };
11
+
12
+ export function escapeHtml(string) {
13
+ return String(string).replace(/[&<>"'/]/g, s => entityMap[s]);
14
+ }
15
+
16
+ export function ajax(url, settings) {
17
+ settings = settings || {};
18
+ settings.headers = settings.headers || {};
19
+ settings.headers["X-SILENCE-LOGGER"] = true;
20
+ return Em.$.ajax(Preload.get("rootPath") + url, settings);
21
+ }
22
+
23
+ export function preloadOrAjax(url, settings) {
24
+ const preloaded = Preload.get(`preload.${url.replace(".json", "")}`);
25
+ if (preloaded) {
26
+ return Em.RSVP.resolve(preloaded);
27
+ } else {
28
+ return ajax(url, settings);
29
+ }
30
+ }
31
+
32
+ let HIDDEN_PROPERTY;
33
+ let TITLE;
34
+ let TITLE_COUNT;
35
+
36
+ export function updateHiddenProperty(property) {
37
+ HIDDEN_PROPERTY = property;
38
+ }
39
+
40
+ export function isHidden() {
41
+ if (HIDDEN_PROPERTY !== undefined) {
42
+ return document[HIDDEN_PROPERTY];
43
+ } else {
44
+ return !document.hasFocus;
45
+ }
46
+ }
47
+
48
+ export function increaseTitleCount(increment) {
49
+ if (!isHidden()) {
50
+ return;
51
+ }
52
+ TITLE = TITLE || document.title;
53
+ TITLE_COUNT = TITLE_COUNT || 0;
54
+ TITLE_COUNT += increment;
55
+ document.title = `${TITLE} (${TITLE_COUNT})`;
56
+ }
57
+
58
+ export function resetTitleCount() {
59
+ TITLE_COUNT = 0;
60
+ document.title = TITLE || document.title;
61
+ }
62
+
63
+ export function formatTime(timestamp) {
64
+ let formatted;
65
+ const time = moment(timestamp);
66
+ const now = moment();
67
+
68
+ if (time.diff(now.startOf("day")) > 0) {
69
+ formatted = time.format("h:mm a");
70
+ } else {
71
+ if (time.diff(now.startOf("week")) > 0) {
72
+ formatted = time.format("dd h:mm a");
73
+ } else {
74
+ if (time.diff(now.startOf("year")) > 0) {
75
+ formatted = time.format("D MMM h:mm a");
76
+ } else {
77
+ formatted = time.format("D MMM YY");
78
+ }
79
+ }
80
+ }
81
+
82
+ return formatted;
83
+ }
84
+
85
+ export function buildArrayString(array) {
86
+ const buffer = [];
87
+ array.forEach(v => {
88
+ if (v === null) {
89
+ buffer.push("null");
90
+ } else if (Object.prototype.toString.call(v) === "[object Array]") {
91
+ buffer.push(buildArrayString(v));
92
+ } else {
93
+ buffer.push(escapeHtml(v.toString()));
94
+ }
95
+ });
96
+ return "[" + buffer.join(", ") + "]";
97
+ }
98
+
99
+ export function buildHashString(hash, recurse) {
100
+ if (!hash) return "";
101
+
102
+ const buffer = [];
103
+ const hashes = [];
104
+ _.each(hash, (v, k) => {
105
+ if (v === null) {
106
+ buffer.push("null");
107
+ } else if (Object.prototype.toString.call(v) === "[object Array]") {
108
+ buffer.push(
109
+ "<tr><td>" +
110
+ escapeHtml(k) +
111
+ "</td><td>" +
112
+ buildArrayString(v) +
113
+ "</td></tr>"
114
+ );
115
+ } else if (typeof v === "object") {
116
+ hashes.push(k);
117
+ } else {
118
+ buffer.push(
119
+ "<tr><td>" + escapeHtml(k) + "</td><td>" + escapeHtml(v) + "</td></tr>"
120
+ );
121
+ }
122
+ });
123
+
124
+ if (_.size(hashes) > 0) {
125
+ _.each(hashes, function(k1) {
126
+ const v = hash[k1];
127
+ buffer.push("<tr><td></td><td><table>");
128
+ buffer.push(
129
+ "<td>" +
130
+ escapeHtml(k1) +
131
+ "</td><td>" +
132
+ buildHashString(v, true) +
133
+ "</td>"
134
+ );
135
+ buffer.push("</table></td></tr>");
136
+ });
137
+ }
138
+ const className = recurse ? "" : "env-table";
139
+ return "<table class='" + className + "'>" + buffer.join("\n") + "</table>";
140
+ }