logster 2.1.2 → 2.2.0
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.
- checksums.yaml +4 -4
- data/.gitignore +21 -19
- data/.rubocop.yml +1 -1
- data/.travis.yml +16 -16
- data/CHANGELOG.md +224 -172
- data/Gemfile +4 -4
- data/Guardfile +8 -8
- data/LICENSE.txt +22 -22
- data/README.md +99 -99
- data/Rakefile +21 -21
- data/assets/fonts/FontAwesome.otf +0 -0
- data/assets/fonts/fontawesome-webfont.eot +0 -0
- data/assets/fonts/fontawesome-webfont.svg +639 -639
- data/assets/fonts/fontawesome-webfont.ttf +0 -0
- data/assets/fonts/fontawesome-webfont.woff +0 -0
- data/assets/fonts/fontawesome-webfont.woff2 +0 -0
- data/assets/images/Icon-144_rounded.png +0 -0
- data/assets/images/Icon-144_square.png +0 -0
- data/assets/images/icon_144x144.png +0 -0
- data/assets/images/icon_64x64.png +0 -0
- data/assets/javascript/client-app.js +115 -106
- data/assets/stylesheets/client-app.css +1 -1
- data/build_client_app.sh +0 -0
- data/client-app/.editorconfig +20 -20
- data/client-app/.ember-cli +9 -9
- data/client-app/.eslintignore +19 -19
- data/client-app/.eslintrc.js +46 -46
- data/client-app/.gitignore +23 -23
- data/client-app/.travis.yml +27 -27
- data/client-app/.watchmanconfig +3 -3
- data/client-app/README.md +57 -57
- data/client-app/app/app.js +0 -0
- data/client-app/app/components/actions-menu.js +43 -43
- data/client-app/app/components/env-tab.js +80 -80
- data/client-app/app/components/message-info.js +0 -0
- data/client-app/app/components/message-row.js +0 -0
- data/client-app/app/components/panel-resizer.js +0 -0
- data/client-app/app/components/patterns-list.js +109 -0
- data/client-app/app/components/tab-contents.js +27 -27
- data/client-app/app/components/tabbed-section.js +0 -0
- data/client-app/app/components/time-formatter.js +0 -0
- data/client-app/app/components/update-time.js +0 -0
- data/client-app/app/controllers/index.js +22 -6
- data/client-app/app/controllers/show.js +0 -0
- data/client-app/app/helpers/logster-url.js +12 -0
- data/client-app/app/helpers/or.js +7 -0
- data/client-app/app/index.html +30 -29
- data/client-app/app/initializers/app-init.js +67 -67
- data/client-app/app/lib/preload.js +20 -20
- data/client-app/app/lib/utilities.js +150 -149
- data/client-app/app/models/message-collection.js +0 -0
- data/client-app/app/models/message.js +100 -100
- data/client-app/app/models/pattern-item.js +25 -0
- data/client-app/app/resolver.js +0 -0
- data/client-app/app/router.js +1 -0
- data/client-app/app/routes/index.js +2 -9
- data/client-app/app/routes/settings.js +15 -0
- data/client-app/app/routes/show.js +0 -0
- data/client-app/app/styles/app.css +633 -527
- data/client-app/app/templates/application.hbs +2 -2
- data/client-app/app/templates/components/actions-menu.hbs +12 -12
- data/client-app/app/templates/components/env-tab.hbs +10 -10
- data/client-app/app/templates/components/message-info.hbs +41 -41
- data/client-app/app/templates/components/message-row.hbs +15 -15
- data/client-app/app/templates/components/panel-resizer.hbs +3 -3
- data/client-app/app/templates/components/patterns-list.hbs +25 -0
- data/client-app/app/templates/components/tabbed-section.hbs +10 -10
- data/client-app/app/templates/components/time-formatter.hbs +1 -1
- data/client-app/app/templates/index.hbs +65 -58
- data/client-app/app/templates/settings.hbs +26 -0
- data/client-app/app/templates/show.hbs +7 -7
- data/client-app/config/environment.js +51 -51
- data/client-app/config/optional-features.json +3 -3
- data/client-app/config/targets.js +18 -18
- data/client-app/ember-cli-build.js +29 -29
- data/client-app/package-lock.json +11357 -11365
- data/client-app/package.json +57 -56
- data/client-app/public/assets/images/icon_144x144.png +0 -0
- data/client-app/public/assets/images/icon_64x64.png +0 -0
- data/client-app/testem.js +25 -25
- data/client-app/tests/index.html +34 -34
- data/client-app/tests/integration/components/env-tab-test.js +134 -123
- data/client-app/tests/integration/components/message-info-test.js +111 -111
- data/client-app/tests/integration/components/patterns-list-test.js +56 -0
- data/client-app/tests/test-helper.js +8 -8
- data/client-app/tests/unit/controllers/index-test.js +12 -12
- data/client-app/tests/unit/controllers/show-test.js +12 -12
- data/client-app/tests/unit/initializers/app-init-test.js +31 -31
- data/client-app/tests/unit/routes/index-test.js +11 -11
- data/client-app/tests/unit/routes/show-test.js +11 -11
- data/lib/examples/sidekiq_logster_reporter.rb +21 -21
- data/lib/logster.rb +59 -54
- data/lib/logster/base_store.rb +169 -141
- data/lib/logster/cache.rb +20 -0
- data/lib/logster/configuration.rb +27 -26
- data/lib/logster/defer_logger.rb +14 -14
- data/lib/logster/ignore_pattern.rb +65 -65
- data/lib/logster/logger.rb +113 -113
- data/lib/logster/message.rb +212 -212
- data/lib/logster/middleware/debug_exceptions.rb +26 -26
- data/lib/logster/middleware/reporter.rb +55 -55
- data/lib/logster/middleware/viewer.rb +297 -222
- data/lib/logster/pattern.rb +95 -0
- data/lib/logster/rails/railtie.rb +63 -63
- data/lib/logster/redis_store.rb +584 -566
- data/lib/logster/scheduler.rb +54 -54
- data/lib/logster/suppression_pattern.rb +17 -0
- data/lib/logster/version.rb +3 -3
- data/lib/logster/web.rb +14 -14
- data/logster.gemspec +35 -35
- data/test/examples/test_sidekiq_reporter_example.rb +46 -46
- data/test/fake_data/Gemfile +4 -4
- data/test/fake_data/generate.rb +10 -10
- data/test/logster/middleware/test_reporter.rb +19 -19
- data/test/logster/middleware/test_viewer.rb +267 -96
- data/test/logster/test_base_store.rb +147 -147
- data/test/logster/test_cache.rb +38 -0
- data/test/logster/test_defer_logger.rb +34 -34
- data/test/logster/test_ignore_pattern.rb +41 -41
- data/test/logster/test_logger.rb +100 -86
- data/test/logster/test_message.rb +119 -119
- data/test/logster/test_pattern.rb +152 -0
- data/test/logster/test_redis_rate_limiter.rb +230 -230
- data/test/logster/test_redis_store.rb +689 -720
- data/test/test_helper.rb +38 -38
- data/vendor/assets/javascripts/logster.js.erb +39 -39
- metadata +24 -7
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import Component from "@ember/component";
|
|
2
|
-
|
|
3
|
-
export default Component.extend({
|
|
4
|
-
classNameBindings: ["active", ":content", "name"],
|
|
5
|
-
isLink: false,
|
|
6
|
-
|
|
7
|
-
invokeParent(name) {
|
|
8
|
-
let current = this.get("parentView");
|
|
9
|
-
while (current && !current[name]) {
|
|
10
|
-
current = current.get("parentView");
|
|
11
|
-
}
|
|
12
|
-
if (current) {
|
|
13
|
-
current[name](this);
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
|
|
17
|
-
didInsertElement() {
|
|
18
|
-
this.invokeParent("addTab");
|
|
19
|
-
if (this.get("defaultTab")) {
|
|
20
|
-
this.invokeParent("selectTab");
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
willDestroyElement() {
|
|
25
|
-
this.invokeParent("removeTab");
|
|
26
|
-
}
|
|
27
|
-
});
|
|
1
|
+
import Component from "@ember/component";
|
|
2
|
+
|
|
3
|
+
export default Component.extend({
|
|
4
|
+
classNameBindings: ["active", ":content", "name"],
|
|
5
|
+
isLink: false,
|
|
6
|
+
|
|
7
|
+
invokeParent(name) {
|
|
8
|
+
let current = this.get("parentView");
|
|
9
|
+
while (current && !current[name]) {
|
|
10
|
+
current = current.get("parentView");
|
|
11
|
+
}
|
|
12
|
+
if (current) {
|
|
13
|
+
current[name](this);
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
didInsertElement() {
|
|
18
|
+
this.invokeParent("addTab");
|
|
19
|
+
if (this.get("defaultTab")) {
|
|
20
|
+
this.invokeParent("selectTab");
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
willDestroyElement() {
|
|
25
|
+
this.invokeParent("removeTab");
|
|
26
|
+
}
|
|
27
|
+
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
import Controller from "@ember/controller";
|
|
2
2
|
import { ajax } from "client-app/lib/utilities";
|
|
3
3
|
import { observer, computed } from "@ember/object";
|
|
4
|
+
import Preload from "client-app/lib/preload";
|
|
4
5
|
|
|
5
6
|
export default Controller.extend({
|
|
7
|
+
showDebug: true,
|
|
8
|
+
showInfo: true,
|
|
9
|
+
showWarn: true,
|
|
10
|
+
showErr: true,
|
|
11
|
+
showFatal: true,
|
|
12
|
+
search: "",
|
|
6
13
|
currentMessage: Em.computed.alias("model.currentMessage"),
|
|
7
14
|
|
|
15
|
+
showSettings: computed(function() {
|
|
16
|
+
return Preload.get("patterns_enabled");
|
|
17
|
+
}),
|
|
18
|
+
|
|
8
19
|
resizePanels(amount) {
|
|
9
20
|
Em.$("#bottom-panel").css("height", amount - 13);
|
|
10
21
|
Em.$("#top-panel").css("bottom", amount + 12);
|
|
@@ -69,7 +80,7 @@ export default Controller.extend({
|
|
|
69
80
|
}
|
|
70
81
|
},
|
|
71
82
|
|
|
72
|
-
|
|
83
|
+
filter: computed(
|
|
73
84
|
"showDebug",
|
|
74
85
|
"showInfo",
|
|
75
86
|
"showWarn",
|
|
@@ -85,14 +96,19 @@ export default Controller.extend({
|
|
|
85
96
|
|
|
86
97
|
// always show unknown, rare
|
|
87
98
|
filter.push(5);
|
|
88
|
-
|
|
89
|
-
model.set("filter", filter);
|
|
90
|
-
if (this.get("initialized")) {
|
|
91
|
-
model.reload().then(() => this.updateSelectedMessage());
|
|
92
|
-
}
|
|
99
|
+
return filter;
|
|
93
100
|
}
|
|
94
101
|
),
|
|
95
102
|
|
|
103
|
+
filterChanged: observer("filter.length", function() {
|
|
104
|
+
const filter = this.get("filter");
|
|
105
|
+
const model = this.get("model");
|
|
106
|
+
model.set("filter", filter);
|
|
107
|
+
if (filter && this.get("initialized")) {
|
|
108
|
+
model.reload().then(() => this.updateSelectedMessage());
|
|
109
|
+
}
|
|
110
|
+
}),
|
|
111
|
+
|
|
96
112
|
searchChanged: observer("search", function() {
|
|
97
113
|
const search = this.get("search");
|
|
98
114
|
const model = this.get("model");
|
|
File without changes
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { helper } from "@ember/component/helper";
|
|
2
|
+
import Preload from "client-app/lib/preload";
|
|
3
|
+
|
|
4
|
+
export function logsterUrl(arr) {
|
|
5
|
+
let url = arr[0];
|
|
6
|
+
if (url[0] !== "/") {
|
|
7
|
+
url = `/${url}`;
|
|
8
|
+
}
|
|
9
|
+
return Preload.get("rootPath") + url;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default helper(logsterUrl);
|
data/client-app/app/index.html
CHANGED
|
@@ -1,29 +1,30 @@
|
|
|
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, minimum-scale=1.0, maximum-scale=1.0, user-scalable=yes">
|
|
9
|
-
<meta id="preloaded-data" data-root-path="/logs" data-preloaded="{"env_expandable_keys":[]}">
|
|
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
|
-
|
|
17
|
-
<link href='//fonts.googleapis.com/css?family=Roboto
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<script src="{{rootURL}}assets/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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, minimum-scale=1.0, maximum-scale=1.0, user-scalable=yes">
|
|
9
|
+
<meta id="preloaded-data" data-root-path="/logs" data-preloaded="{"env_expandable_keys":[],"patterns_enabled":true}">
|
|
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
|
+
<link rel="shortcut icon" href="{{rootURL}}assets/images/icon_64x64.png">
|
|
16
|
+
|
|
17
|
+
<link href='//fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
|
|
18
|
+
<link href='//fonts.googleapis.com/css?family=Roboto+Mono' rel='stylesheet' type='text/css'>
|
|
19
|
+
|
|
20
|
+
{{content-for "head-footer"}}
|
|
21
|
+
</head>
|
|
22
|
+
<body>
|
|
23
|
+
{{content-for "body"}}
|
|
24
|
+
|
|
25
|
+
<script src="{{rootURL}}assets/vendor.js"></script>
|
|
26
|
+
<script src="{{rootURL}}assets/client-app.js"></script>
|
|
27
|
+
|
|
28
|
+
{{content-for "body-footer"}}
|
|
29
|
+
</body>
|
|
30
|
+
</html>
|
|
@@ -1,67 +1,67 @@
|
|
|
1
|
-
import {
|
|
2
|
-
updateHiddenProperty,
|
|
3
|
-
resetTitleCount
|
|
4
|
-
} from "client-app/lib/utilities";
|
|
5
|
-
import Evented from "@ember/object/evented";
|
|
6
|
-
import EmberObject from "@ember/object";
|
|
7
|
-
|
|
8
|
-
const TARGETS = ["component", "route"];
|
|
9
|
-
|
|
10
|
-
export function initialize(app) {
|
|
11
|
-
// config for moment.js
|
|
12
|
-
moment.updateLocale("en", {
|
|
13
|
-
relativeTime: {
|
|
14
|
-
future: "in %s",
|
|
15
|
-
past: "%s ago",
|
|
16
|
-
s: "secs",
|
|
17
|
-
m: "a min",
|
|
18
|
-
mm: "%d mins",
|
|
19
|
-
h: "an hr",
|
|
20
|
-
hh: "%d hrs",
|
|
21
|
-
d: "a day",
|
|
22
|
-
dd: "%d days",
|
|
23
|
-
M: "a mth",
|
|
24
|
-
MM: "%d mths",
|
|
25
|
-
y: "a yr",
|
|
26
|
-
yy: "%d yrs"
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
// setup event for updating document title and title count
|
|
31
|
-
let hiddenProperty;
|
|
32
|
-
let visibilitychange;
|
|
33
|
-
|
|
34
|
-
["", "webkit", "ms", "moz", "ms"].forEach(prefix => {
|
|
35
|
-
const check = prefix + (prefix === "" ? "hidden" : "Hidden");
|
|
36
|
-
if (document[check] !== undefined && !hiddenProperty) {
|
|
37
|
-
hiddenProperty = check;
|
|
38
|
-
visibilitychange = prefix + "visibilitychange";
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
updateHiddenProperty(hiddenProperty);
|
|
43
|
-
document.addEventListener(
|
|
44
|
-
visibilitychange,
|
|
45
|
-
() => {
|
|
46
|
-
resetTitleCount();
|
|
47
|
-
},
|
|
48
|
-
false
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
app.register("events:main", EmberObject.extend(Evented).create(), {
|
|
52
|
-
instantiate: false
|
|
53
|
-
});
|
|
54
|
-
TARGETS.forEach(t => app.inject(t, "events", "events:main"));
|
|
55
|
-
|
|
56
|
-
const isMobile =
|
|
57
|
-
/mobile/i.test(navigator.userAgent) && !/iPad/.test(navigator.userAgent);
|
|
58
|
-
if (isMobile) {
|
|
59
|
-
Em.$("body").addClass("mobile");
|
|
60
|
-
}
|
|
61
|
-
app.register("site:main", { isMobile }, { instantiate: false });
|
|
62
|
-
app.inject("controller", "site", "site:main");
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export default {
|
|
66
|
-
initialize
|
|
67
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
updateHiddenProperty,
|
|
3
|
+
resetTitleCount
|
|
4
|
+
} from "client-app/lib/utilities";
|
|
5
|
+
import Evented from "@ember/object/evented";
|
|
6
|
+
import EmberObject from "@ember/object";
|
|
7
|
+
|
|
8
|
+
const TARGETS = ["component", "route"];
|
|
9
|
+
|
|
10
|
+
export function initialize(app) {
|
|
11
|
+
// config for moment.js
|
|
12
|
+
moment.updateLocale("en", {
|
|
13
|
+
relativeTime: {
|
|
14
|
+
future: "in %s",
|
|
15
|
+
past: "%s ago",
|
|
16
|
+
s: "secs",
|
|
17
|
+
m: "a min",
|
|
18
|
+
mm: "%d mins",
|
|
19
|
+
h: "an hr",
|
|
20
|
+
hh: "%d hrs",
|
|
21
|
+
d: "a day",
|
|
22
|
+
dd: "%d days",
|
|
23
|
+
M: "a mth",
|
|
24
|
+
MM: "%d mths",
|
|
25
|
+
y: "a yr",
|
|
26
|
+
yy: "%d yrs"
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// setup event for updating document title and title count
|
|
31
|
+
let hiddenProperty;
|
|
32
|
+
let visibilitychange;
|
|
33
|
+
|
|
34
|
+
["", "webkit", "ms", "moz", "ms"].forEach(prefix => {
|
|
35
|
+
const check = prefix + (prefix === "" ? "hidden" : "Hidden");
|
|
36
|
+
if (document[check] !== undefined && !hiddenProperty) {
|
|
37
|
+
hiddenProperty = check;
|
|
38
|
+
visibilitychange = prefix + "visibilitychange";
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
updateHiddenProperty(hiddenProperty);
|
|
43
|
+
document.addEventListener(
|
|
44
|
+
visibilitychange,
|
|
45
|
+
() => {
|
|
46
|
+
resetTitleCount();
|
|
47
|
+
},
|
|
48
|
+
false
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
app.register("events:main", EmberObject.extend(Evented).create(), {
|
|
52
|
+
instantiate: false
|
|
53
|
+
});
|
|
54
|
+
TARGETS.forEach(t => app.inject(t, "events", "events:main"));
|
|
55
|
+
|
|
56
|
+
const isMobile =
|
|
57
|
+
/mobile/i.test(navigator.userAgent) && !/iPad/.test(navigator.userAgent);
|
|
58
|
+
if (isMobile) {
|
|
59
|
+
Em.$("body").addClass("mobile");
|
|
60
|
+
}
|
|
61
|
+
app.register("site:main", { isMobile }, { instantiate: false });
|
|
62
|
+
app.inject("controller", "site", "site:main");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default {
|
|
66
|
+
initialize
|
|
67
|
+
};
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
let CONTAINER;
|
|
2
|
-
let isInitialized = false;
|
|
3
|
-
|
|
4
|
-
// exported so that it can be used in tests
|
|
5
|
-
export function init() {
|
|
6
|
-
const dataset = document.getElementById("preloaded-data").dataset;
|
|
7
|
-
CONTAINER = Em.$.extend(JSON.parse(dataset.preloaded), {
|
|
8
|
-
rootPath: dataset.rootPath
|
|
9
|
-
});
|
|
10
|
-
isInitialized = true;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export default {
|
|
14
|
-
get(key) {
|
|
15
|
-
if (!isInitialized) {
|
|
16
|
-
init();
|
|
17
|
-
}
|
|
18
|
-
return Em.get(CONTAINER, key);
|
|
19
|
-
}
|
|
20
|
-
};
|
|
1
|
+
let CONTAINER;
|
|
2
|
+
let isInitialized = false;
|
|
3
|
+
|
|
4
|
+
// exported so that it can be used in tests
|
|
5
|
+
export function init() {
|
|
6
|
+
const dataset = document.getElementById("preloaded-data").dataset;
|
|
7
|
+
CONTAINER = Em.$.extend(JSON.parse(dataset.preloaded), {
|
|
8
|
+
rootPath: dataset.rootPath
|
|
9
|
+
});
|
|
10
|
+
isInitialized = true;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default {
|
|
14
|
+
get(key) {
|
|
15
|
+
if (!isInitialized) {
|
|
16
|
+
init();
|
|
17
|
+
}
|
|
18
|
+
return Em.get(CONTAINER, key);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
@@ -1,149 +1,150 @@
|
|
|
1
|
-
import Preload from "client-app/lib/preload";
|
|
2
|
-
|
|
3
|
-
const entityMap = {
|
|
4
|
-
"&": "&",
|
|
5
|
-
"<": "<",
|
|
6
|
-
">": ">",
|
|
7
|
-
'"': """,
|
|
8
|
-
"'": "'",
|
|
9
|
-
"/": "/"
|
|
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(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, expanded = []) {
|
|
100
|
-
if (!hash) return "";
|
|
101
|
-
|
|
102
|
-
const buffer = [];
|
|
103
|
-
const hashes = [];
|
|
104
|
-
const expandableKeys = Preload.get("env_expandable_keys") || [];
|
|
105
|
-
_.each(hash, (v, k) => {
|
|
106
|
-
if (v === null) {
|
|
107
|
-
buffer.push("null");
|
|
108
|
-
} else if (Object.prototype.toString.call(v) === "[object Array]") {
|
|
109
|
-
let valueHtml = "";
|
|
110
|
-
if (
|
|
111
|
-
expandableKeys.indexOf(k) !== -1 &&
|
|
112
|
-
!recurse &&
|
|
113
|
-
expanded.indexOf(k) === -1
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
buffer.push(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
1
|
+
import Preload from "client-app/lib/preload";
|
|
2
|
+
|
|
3
|
+
const entityMap = {
|
|
4
|
+
"&": "&",
|
|
5
|
+
"<": "<",
|
|
6
|
+
">": ">",
|
|
7
|
+
'"': """,
|
|
8
|
+
"'": "'",
|
|
9
|
+
"/": "/"
|
|
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(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, expanded = []) {
|
|
100
|
+
if (!hash) return "";
|
|
101
|
+
|
|
102
|
+
const buffer = [];
|
|
103
|
+
const hashes = [];
|
|
104
|
+
const expandableKeys = Preload.get("env_expandable_keys") || [];
|
|
105
|
+
_.each(hash, (v, k) => {
|
|
106
|
+
if (v === null) {
|
|
107
|
+
buffer.push("null");
|
|
108
|
+
} else if (Object.prototype.toString.call(v) === "[object Array]") {
|
|
109
|
+
let valueHtml = "";
|
|
110
|
+
if (
|
|
111
|
+
expandableKeys.indexOf(k) !== -1 &&
|
|
112
|
+
!recurse &&
|
|
113
|
+
expanded.indexOf(k) === -1 &&
|
|
114
|
+
v.length > 3
|
|
115
|
+
) {
|
|
116
|
+
valueHtml = `${escapeHtml(
|
|
117
|
+
v[0]
|
|
118
|
+
)}, <a class="expand-list" data-key=${k}>${v.length - 1} more</a>`;
|
|
119
|
+
} else {
|
|
120
|
+
valueHtml = buildArrayString(v);
|
|
121
|
+
}
|
|
122
|
+
buffer.push(
|
|
123
|
+
"<tr><td>" + escapeHtml(k) + "</td><td>" + valueHtml + "</td></tr>"
|
|
124
|
+
);
|
|
125
|
+
} else if (typeof v === "object") {
|
|
126
|
+
hashes.push(k);
|
|
127
|
+
} else {
|
|
128
|
+
buffer.push(
|
|
129
|
+
"<tr><td>" + escapeHtml(k) + "</td><td>" + escapeHtml(v) + "</td></tr>"
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
if (_.size(hashes) > 0) {
|
|
135
|
+
_.each(hashes, function(k1) {
|
|
136
|
+
const v = hash[k1];
|
|
137
|
+
buffer.push("<tr><td></td><td><table>");
|
|
138
|
+
buffer.push(
|
|
139
|
+
"<td>" +
|
|
140
|
+
escapeHtml(k1) +
|
|
141
|
+
"</td><td>" +
|
|
142
|
+
buildHashString(v, true) +
|
|
143
|
+
"</td>"
|
|
144
|
+
);
|
|
145
|
+
buffer.push("</table></td></tr>");
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
const className = recurse ? "" : "env-table";
|
|
149
|
+
return "<table class='" + className + "'>" + buffer.join("\n") + "</table>";
|
|
150
|
+
}
|