logster 2.11.4 → 2.12.2
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/.github/workflows/ci.yml +63 -12
- data/.gitignore +2 -0
- data/CHANGELOG.md +15 -5
- data/README.md +8 -0
- data/assets/javascript/.gitkeep +0 -0
- data/assets/javascript/chunk.143.f61340b825c6a3bf6dbe.js +22 -0
- data/assets/javascript/chunk.178.6d9ae01775c898e7b748.js +22 -0
- data/assets/javascript/chunk.468.95dd450003497c781cb3.js +1213 -0
- data/assets/javascript/chunk.916.85a3fc9d873df80f5ea5.js +579 -0
- data/assets/javascript/client-app.js +1259 -280
- data/assets/javascript/vendor.js +4068 -3375
- data/assets/stylesheets/.gitkeep +0 -0
- data/assets/stylesheets/client-app.css +1 -1
- data/assets/stylesheets/vendor.css +1 -1
- data/build_client_app.sh +6 -8
- data/client-app/.editorconfig +0 -1
- data/client-app/.eslintignore +2 -0
- data/client-app/.eslintrc +10 -0
- data/client-app/.gitignore +1 -1
- data/client-app/.prettierignore +21 -0
- data/client-app/.prettierrc +1 -0
- data/client-app/.template-lintrc.js +10 -0
- data/client-app/README.md +4 -5
- data/client-app/app/app.js +2 -2
- data/client-app/app/components/actions-menu.js +21 -21
- data/client-app/app/components/back-trace.js +93 -90
- data/client-app/app/components/env-tab.js +41 -29
- data/client-app/app/components/message-info.js +78 -75
- data/client-app/app/components/message-row.js +20 -17
- data/client-app/app/components/page-nav.js +33 -24
- data/client-app/app/components/panel-resizer.js +53 -37
- data/client-app/app/components/patterns-list.js +101 -84
- data/client-app/app/components/tab-contents.js +15 -19
- data/client-app/app/components/tabbed-section.js +30 -18
- data/client-app/app/components/time-formatter.js +29 -18
- data/client-app/app/controllers/index.js +143 -119
- data/client-app/app/controllers/show.js +17 -13
- data/client-app/app/helpers/or.js +1 -1
- data/client-app/app/initializers/app-init.js +23 -34
- data/client-app/app/lib/decorators.js +4 -2
- data/client-app/app/lib/preload.js +7 -4
- data/client-app/app/lib/utilities.js +55 -54
- data/client-app/app/models/group.js +20 -15
- data/client-app/app/models/message-collection.js +153 -149
- data/client-app/app/models/message.js +60 -58
- data/client-app/app/models/pattern-item.js +24 -22
- data/client-app/app/router.js +2 -2
- data/client-app/app/routes/index.js +19 -12
- data/client-app/app/routes/settings.js +12 -10
- data/client-app/app/routes/show.js +6 -4
- data/client-app/app/services/events.js +4 -0
- data/client-app/app/styles/app.css +2 -0
- data/client-app/app/templates/application.hbs +1 -2
- data/client-app/app/templates/components/actions-menu.hbs +23 -8
- data/client-app/app/templates/components/back-trace.hbs +10 -3
- data/client-app/app/templates/components/env-tab.hbs +9 -7
- data/client-app/app/templates/components/message-info.hbs +65 -34
- data/client-app/app/templates/components/message-row.hbs +25 -8
- data/client-app/app/templates/components/page-nav.hbs +34 -10
- data/client-app/app/templates/components/panel-resizer.hbs +3 -3
- data/client-app/app/templates/components/patterns-list.hbs +54 -20
- data/client-app/app/templates/components/tabbed-section.hbs +12 -4
- data/client-app/app/templates/components/time-formatter.hbs +1 -1
- data/client-app/app/templates/index.hbs +100 -78
- data/client-app/app/templates/settings.hbs +30 -19
- data/client-app/app/templates/show.hbs +9 -8
- data/client-app/config/ember-cli-update.json +18 -0
- data/client-app/config/environment.js +13 -13
- data/client-app/config/icons.js +3 -3
- data/client-app/config/targets.js +16 -8
- data/client-app/ember-cli-build.js +4 -4
- data/client-app/package.json +41 -31
- data/client-app/testem.js +16 -17
- data/client-app/tests/index.html +8 -1
- data/client-app/tests/integration/components/back-trace-test.js +49 -26
- data/client-app/tests/integration/components/env-tab-test.js +79 -53
- data/client-app/tests/integration/components/message-info-test.js +25 -23
- data/client-app/tests/integration/components/patterns-list-test.js +14 -11
- data/client-app/tests/test-helper.js +8 -4
- data/client-app/tests/unit/controllers/index-test.js +32 -16
- data/client-app/tests/unit/controllers/show-test.js +5 -5
- data/client-app/tests/unit/routes/index-test.js +5 -5
- data/client-app/tests/unit/routes/show-test.js +5 -5
- data/client-app/yarn.lock +9673 -0
- data/lib/logster/version.rb +1 -1
- data/logster.gemspec +6 -3
- metadata +15 -6
- data/client-app/.eslintrc.js +0 -60
- data/client-app/.travis.yml +0 -28
- data/client-app/app/components/update-time.js +0 -21
- data/client-app/package-lock.json +0 -16639
|
@@ -1,19 +1,23 @@
|
|
|
1
|
+
import classic from "ember-classic-decorator";
|
|
1
2
|
import Controller from "@ember/controller";
|
|
3
|
+
import { action } from "@ember/object";
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
@classic
|
|
6
|
+
export default class ShowController extends Controller {
|
|
7
|
+
envPosition = 0;
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
@action
|
|
10
|
+
protect() {
|
|
11
|
+
this.model.protect();
|
|
12
|
+
}
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
@action
|
|
15
|
+
unprotect() {
|
|
16
|
+
this.model.unprotect();
|
|
17
|
+
}
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
@action
|
|
20
|
+
envChanged(newPosition) {
|
|
21
|
+
this.set("envPosition", newPosition);
|
|
18
22
|
}
|
|
19
|
-
}
|
|
23
|
+
}
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
ajax,
|
|
3
3
|
resetTitleCount,
|
|
4
|
-
|
|
4
|
+
updateHiddenProperty,
|
|
5
5
|
} from "client-app/lib/utilities";
|
|
6
|
-
import Evented from "@ember/object/evented";
|
|
7
|
-
import EmberObject from "@ember/object";
|
|
8
6
|
import { setRootPath } from "client-app/lib/preload";
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export function initialize(app) {
|
|
8
|
+
export async function initialize(app) {
|
|
13
9
|
const config = app.resolveRegistration("config:environment");
|
|
14
10
|
setRootPath(config.rootURL.replace(/\/$/, ""));
|
|
15
11
|
|
|
16
12
|
if (config.environment === "development") {
|
|
17
13
|
app.deferReadiness();
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
.
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const data = await ajax("/development-preload.json");
|
|
17
|
+
const elem = document.getElementById("preloaded-data");
|
|
18
|
+
elem.setAttribute("data-preloaded", JSON.stringify(data));
|
|
19
|
+
} catch (xhr) {
|
|
20
|
+
console.error("Fetching preload data failed.", xhr); // eslint-disable-line no-console
|
|
21
|
+
} finally {
|
|
22
|
+
app.advanceReadiness();
|
|
23
|
+
}
|
|
25
24
|
}
|
|
25
|
+
|
|
26
26
|
// config for moment.js
|
|
27
27
|
moment.updateLocale("en", {
|
|
28
28
|
relativeTime: {
|
|
@@ -38,45 +38,34 @@ export function initialize(app) {
|
|
|
38
38
|
M: "a mth",
|
|
39
39
|
MM: "%d mths",
|
|
40
40
|
y: "a yr",
|
|
41
|
-
yy: "%d yrs"
|
|
42
|
-
}
|
|
41
|
+
yy: "%d yrs",
|
|
42
|
+
},
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
// setup event for updating document title and title count
|
|
46
46
|
let hiddenProperty;
|
|
47
47
|
let visibilitychange;
|
|
48
48
|
|
|
49
|
-
["", "webkit", "ms", "moz", "ms"]
|
|
49
|
+
for (const prefix of ["", "webkit", "ms", "moz", "ms"]) {
|
|
50
50
|
const check = prefix + (prefix === "" ? "hidden" : "Hidden");
|
|
51
|
-
|
|
51
|
+
|
|
52
|
+
if (document[check] !== undefined) {
|
|
52
53
|
hiddenProperty = check;
|
|
53
54
|
visibilitychange = prefix + "visibilitychange";
|
|
55
|
+
break;
|
|
54
56
|
}
|
|
55
|
-
}
|
|
57
|
+
}
|
|
56
58
|
|
|
57
59
|
updateHiddenProperty(hiddenProperty);
|
|
58
|
-
document.addEventListener(
|
|
59
|
-
visibilitychange,
|
|
60
|
-
() => {
|
|
61
|
-
resetTitleCount();
|
|
62
|
-
},
|
|
63
|
-
false
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
app.register("events:main", EmberObject.extend(Evented).create(), {
|
|
67
|
-
instantiate: false
|
|
68
|
-
});
|
|
69
|
-
TARGETS.forEach(t => app.inject(t, "events", "events:main"));
|
|
60
|
+
document.addEventListener(visibilitychange, resetTitleCount, false);
|
|
70
61
|
|
|
71
62
|
const isMobile =
|
|
72
63
|
/mobile/i.test(navigator.userAgent) && !/iPad/.test(navigator.userAgent);
|
|
73
64
|
if (isMobile) {
|
|
74
65
|
document.body.classList.add("mobile");
|
|
75
66
|
}
|
|
76
|
-
app.register("site:main", { isMobile }, { instantiate: false });
|
|
77
|
-
app.inject("controller", "site", "site:main");
|
|
78
67
|
}
|
|
79
68
|
|
|
80
69
|
export default {
|
|
81
|
-
initialize
|
|
70
|
+
initialize,
|
|
82
71
|
};
|
|
@@ -3,9 +3,11 @@ export function bound(target, key, desc) {
|
|
|
3
3
|
const boundKey = `_${key}Bound`;
|
|
4
4
|
return {
|
|
5
5
|
get() {
|
|
6
|
-
if (this[boundKey])
|
|
6
|
+
if (this[boundKey]) {
|
|
7
|
+
return this[boundKey];
|
|
8
|
+
}
|
|
7
9
|
this.set(boundKey, orig.bind(this));
|
|
8
10
|
return this[boundKey];
|
|
9
|
-
}
|
|
11
|
+
},
|
|
10
12
|
};
|
|
11
13
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { set } from "@ember/object";
|
|
2
|
+
|
|
1
3
|
let CONTAINER = {};
|
|
2
4
|
let isInitialized = false;
|
|
3
5
|
let rootPath;
|
|
@@ -13,7 +15,7 @@ export function getRootPath() {
|
|
|
13
15
|
// exported so that it can be used in tests
|
|
14
16
|
export function init() {
|
|
15
17
|
const dataset = document.getElementById("preloaded-data").dataset;
|
|
16
|
-
CONTAINER = JSON.parse(dataset.preloaded);
|
|
18
|
+
CONTAINER = dataset.preloaded ? JSON.parse(dataset.preloaded) : {};
|
|
17
19
|
CONTAINER.rootPath = rootPath;
|
|
18
20
|
isInitialized = true;
|
|
19
21
|
}
|
|
@@ -23,8 +25,8 @@ export default {
|
|
|
23
25
|
if (!isInitialized) {
|
|
24
26
|
init();
|
|
25
27
|
}
|
|
26
|
-
return
|
|
27
|
-
}
|
|
28
|
+
return CONTAINER[key];
|
|
29
|
+
},
|
|
28
30
|
};
|
|
29
31
|
|
|
30
32
|
// used in tests
|
|
@@ -32,7 +34,8 @@ export function mutatePreload(key, value) {
|
|
|
32
34
|
if (!isInitialized) {
|
|
33
35
|
init();
|
|
34
36
|
}
|
|
35
|
-
|
|
37
|
+
|
|
38
|
+
set(CONTAINER, key, value);
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
export function uninitialize() {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { Promise, resolve } from "rsvp";
|
|
1
|
+
import Preload, { getRootPath } from "client-app/lib/preload";
|
|
3
2
|
|
|
4
3
|
const entityMap = {
|
|
5
4
|
"&": "&",
|
|
@@ -7,32 +6,36 @@ const entityMap = {
|
|
|
7
6
|
">": ">",
|
|
8
7
|
'"': """,
|
|
9
8
|
"'": "'",
|
|
10
|
-
"/": "/"
|
|
9
|
+
"/": "/",
|
|
11
10
|
};
|
|
12
11
|
|
|
13
12
|
export function escapeHtml(string) {
|
|
14
|
-
return String(string).replace(/[&<>"'/]/g, s => entityMap[s]);
|
|
13
|
+
return String(string).replace(/[&<>"'/]/g, (s) => entityMap[s]);
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
export function ajax(url, settings) {
|
|
17
|
+
// eslint-disable-next-line no-restricted-globals
|
|
18
18
|
return new Promise((resolve, reject) => {
|
|
19
|
-
settings
|
|
19
|
+
settings ||= {};
|
|
20
20
|
const xhr = new XMLHttpRequest();
|
|
21
21
|
url = getRootPath() + url;
|
|
22
|
+
|
|
22
23
|
if (settings.data) {
|
|
23
|
-
for (
|
|
24
|
-
|
|
25
|
-
url +=
|
|
26
|
-
url += `${param}=${encodeURIComponent(settings.data[param])}`;
|
|
24
|
+
for (const [param, value] of Object.entries(settings.data)) {
|
|
25
|
+
url += url.includes("?") ? "&" : "?";
|
|
26
|
+
url += `${param}=${encodeURIComponent(value)}`;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
|
|
29
30
|
xhr.open(settings.method || settings.type || "GET", url);
|
|
30
31
|
xhr.setRequestHeader("X-SILENCE-LOGGER", true);
|
|
32
|
+
|
|
31
33
|
if (settings.headers) {
|
|
32
|
-
for (
|
|
33
|
-
xhr.setRequestHeader(header,
|
|
34
|
+
for (const [header, value] of Object.entries(settings.headers)) {
|
|
35
|
+
xhr.setRequestHeader(header, value);
|
|
34
36
|
}
|
|
35
37
|
}
|
|
38
|
+
|
|
36
39
|
xhr.onreadystatechange = () => {
|
|
37
40
|
if (xhr.readyState === 4) {
|
|
38
41
|
let status = xhr.status;
|
|
@@ -48,16 +51,17 @@ export function ajax(url, settings) {
|
|
|
48
51
|
}
|
|
49
52
|
}
|
|
50
53
|
};
|
|
54
|
+
|
|
51
55
|
xhr.send();
|
|
52
56
|
});
|
|
53
57
|
}
|
|
54
58
|
|
|
55
|
-
export function preloadOrAjax(url, settings) {
|
|
59
|
+
export async function preloadOrAjax(url, settings) {
|
|
56
60
|
const preloaded = Preload.get(url.replace(".json", ""));
|
|
57
61
|
if (preloaded) {
|
|
58
|
-
return
|
|
62
|
+
return preloaded;
|
|
59
63
|
} else {
|
|
60
|
-
return ajax(url, settings);
|
|
64
|
+
return await ajax(url, settings);
|
|
61
65
|
}
|
|
62
66
|
}
|
|
63
67
|
|
|
@@ -81,8 +85,9 @@ export function increaseTitleCount(increment) {
|
|
|
81
85
|
if (!isHidden()) {
|
|
82
86
|
return;
|
|
83
87
|
}
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
|
|
89
|
+
TITLE ||= document.title;
|
|
90
|
+
TITLE_COUNT ||= 0;
|
|
86
91
|
TITLE_COUNT += increment;
|
|
87
92
|
document.title = `${TITLE} (${TITLE_COUNT})`;
|
|
88
93
|
}
|
|
@@ -93,57 +98,52 @@ export function resetTitleCount() {
|
|
|
93
98
|
}
|
|
94
99
|
|
|
95
100
|
export function formatTime(timestamp) {
|
|
96
|
-
let formatted;
|
|
97
101
|
const time = moment(timestamp);
|
|
98
102
|
const now = moment();
|
|
99
103
|
|
|
100
104
|
if (time.diff(now.startOf("day")) > 0) {
|
|
101
|
-
|
|
105
|
+
return time.format("h:mm a");
|
|
106
|
+
} else if (time.diff(now.startOf("week")) > 0) {
|
|
107
|
+
return time.format("dd h:mm a");
|
|
108
|
+
} else if (time.diff(now.startOf("year")) > 0) {
|
|
109
|
+
return time.format("D MMM h:mm a");
|
|
102
110
|
} else {
|
|
103
|
-
|
|
104
|
-
formatted = time.format("dd h:mm a");
|
|
105
|
-
} else {
|
|
106
|
-
if (time.diff(now.startOf("year")) > 0) {
|
|
107
|
-
formatted = time.format("D MMM h:mm a");
|
|
108
|
-
} else {
|
|
109
|
-
formatted = time.format("D MMM YY");
|
|
110
|
-
}
|
|
111
|
-
}
|
|
111
|
+
return time.format("D MMM YY");
|
|
112
112
|
}
|
|
113
|
-
|
|
114
|
-
return formatted;
|
|
115
113
|
}
|
|
116
114
|
|
|
117
115
|
export function buildArrayString(array) {
|
|
118
|
-
const buffer =
|
|
119
|
-
array.forEach(v => {
|
|
116
|
+
const buffer = array.map((v) => {
|
|
120
117
|
if (v === null) {
|
|
121
|
-
|
|
122
|
-
} else if (
|
|
123
|
-
|
|
118
|
+
return "null";
|
|
119
|
+
} else if (Array.isArray(v)) {
|
|
120
|
+
return buildArrayString(v);
|
|
124
121
|
} else {
|
|
125
|
-
|
|
122
|
+
return escapeHtml(v.toString());
|
|
126
123
|
}
|
|
127
124
|
});
|
|
125
|
+
|
|
128
126
|
return "[" + buffer.join(", ") + "]";
|
|
129
127
|
}
|
|
130
128
|
|
|
131
129
|
export function buildHashString(hash, recurse, expanded = []) {
|
|
132
|
-
if (!hash)
|
|
130
|
+
if (!hash) {
|
|
131
|
+
return "";
|
|
132
|
+
}
|
|
133
133
|
|
|
134
134
|
const buffer = [];
|
|
135
135
|
const hashes = [];
|
|
136
136
|
const expandableKeys = Preload.get("env_expandable_keys") || [];
|
|
137
|
-
|
|
138
|
-
|
|
137
|
+
|
|
138
|
+
for (const [k, v] of Object.entries(hash)) {
|
|
139
139
|
if (v === null) {
|
|
140
140
|
buffer.push("null");
|
|
141
141
|
} else if (Object.prototype.toString.call(v) === "[object Array]") {
|
|
142
142
|
let valueHtml = "";
|
|
143
143
|
if (
|
|
144
|
-
expandableKeys.
|
|
144
|
+
expandableKeys.includes(k) &&
|
|
145
145
|
!recurse &&
|
|
146
|
-
expanded.
|
|
146
|
+
!expanded.includes(k) &&
|
|
147
147
|
v.length > 3
|
|
148
148
|
) {
|
|
149
149
|
valueHtml = `${escapeHtml(
|
|
@@ -168,18 +168,17 @@ export function buildHashString(hash, recurse, expanded = []) {
|
|
|
168
168
|
);
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
|
-
}
|
|
171
|
+
}
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
buffer.push("</table></td></tr>");
|
|
181
|
-
});
|
|
173
|
+
for (const k1 of hashes) {
|
|
174
|
+
const v = hash[k1];
|
|
175
|
+
buffer.push("<tr><td></td><td><table>");
|
|
176
|
+
buffer.push(
|
|
177
|
+
`<td>${escapeHtml(k1)}</td><td>${buildHashString(v, true)}</td>`
|
|
178
|
+
);
|
|
179
|
+
buffer.push("</table></td></tr>");
|
|
182
180
|
}
|
|
181
|
+
|
|
183
182
|
const className = recurse ? "" : "env-table";
|
|
184
183
|
return `<table class='${className}'>${buffer.join("\n")}</table>`;
|
|
185
184
|
}
|
|
@@ -188,9 +187,9 @@ export function clone(object) {
|
|
|
188
187
|
// simple function to clone an object
|
|
189
188
|
// we don't need it fancier than this
|
|
190
189
|
const copy = {};
|
|
191
|
-
Object.
|
|
192
|
-
copy[k] =
|
|
193
|
-
}
|
|
190
|
+
for (const [k, v] of Object.entries(object)) {
|
|
191
|
+
copy[k] = v;
|
|
192
|
+
}
|
|
194
193
|
return copy;
|
|
195
194
|
}
|
|
196
195
|
|
|
@@ -200,7 +199,9 @@ export function setLocalStorage(key, value) {
|
|
|
200
199
|
key = "logster-" + key;
|
|
201
200
|
window.localStorage.setItem(key, value);
|
|
202
201
|
}
|
|
203
|
-
} catch {
|
|
202
|
+
} catch {
|
|
203
|
+
/* do nothing */
|
|
204
|
+
}
|
|
204
205
|
}
|
|
205
206
|
|
|
206
207
|
export function getLocalStorage(key, fallback) {
|
|
@@ -1,29 +1,34 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { default as EmberObject, computed } from "@ember/object";
|
|
1
|
+
import classic from "ember-classic-decorator";
|
|
3
2
|
import { reads } from "@ember/object/computed";
|
|
3
|
+
import Message from "client-app/models/message";
|
|
4
|
+
import EmberObject, { computed } from "@ember/object";
|
|
4
5
|
import { ajax } from "client-app/lib/utilities";
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
@classic
|
|
8
|
+
export default class Group extends EmberObject {
|
|
9
|
+
selected = false;
|
|
10
|
+
showCount = true;
|
|
11
|
+
|
|
12
|
+
@reads("regex") key;
|
|
13
|
+
@reads("messages.firstObject.message") displayMessage;
|
|
11
14
|
|
|
12
15
|
init() {
|
|
13
|
-
|
|
14
|
-
const messages = this.messages.map(m => Message.create(m));
|
|
16
|
+
super.init(...arguments);
|
|
17
|
+
const messages = this.messages.map((m) => Message.create(m));
|
|
15
18
|
this.set("messages", messages);
|
|
16
|
-
}
|
|
19
|
+
}
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
@computed
|
|
22
|
+
get glyph() {
|
|
19
23
|
return "clone";
|
|
20
|
-
}
|
|
24
|
+
}
|
|
21
25
|
|
|
22
|
-
|
|
26
|
+
@computed
|
|
27
|
+
get prefix() {
|
|
23
28
|
return "far";
|
|
24
|
-
}
|
|
29
|
+
}
|
|
25
30
|
|
|
26
31
|
solveAll() {
|
|
27
32
|
return ajax("/solve-group", { type: "POST", data: { regex: this.regex } });
|
|
28
33
|
}
|
|
29
|
-
}
|
|
34
|
+
}
|