EUIFication: Grok Debugger (#20027)

* Move <kbn-dev-tools-app> Angular wrapper directive usage into route template

* Move sole directive into new directives folder

* WIP checkin: basic conversion to React components

* Fix sample custom patterns indentation

* Remove custom CSS

* Wrap button in EuiFormRow + define isSimulateDisabled

* Wire up simulate

* Cleanup

* Ace formatting options

* Better styling

* Adding spacing between custom patterns and simulate button

* Fixing form row widths

* Removing form row around button

* Add indentation/newlines in structured output

* Error handling

* Use constants

* Removing no-longer-used code

* Implement syntax highlighting via custom mode

* Making functional tests pass

* Adding trailing comma back

* Removing fixed heights

* Removing unnecessary styles

* Make Event Output form row full width as well

* Wrapping EuiCodeEditors in EuiPanels

* Adding spacer before callout; making spacing around callout consistent

* Clear out custom patterns from request if field is cleared out

* Clear out simulation results before attempting simulation

* Set state with untrimmed value
This commit is contained in:
Shaunak Kashyap 2018-06-22 11:51:27 -07:00
parent 09a0ffe350
commit 30c8ccd41c
30 changed files with 319 additions and 472 deletions

View file

@ -9,6 +9,4 @@ export const EDITOR = {
PATTERN_MAX_LINES: 10,
SAMPLE_DATA_MIN_LINES: 3,
SAMPLE_DATA_MAX_LINES: 50,
SCROLL_MARGIN_TOP_PX: 4,
SCROLL_MARGIN_BOTTOM_PX: 4,
};

View file

@ -1,32 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { EDITOR } from '../../../common/constants';
export function applyEditorOptions(editor, minLines, maxLines) {
editor.getSession().setUseWrapMode(true);
/*
* This sets the space between the editor's borders and the
* edges of the top/bottom lines to make for a less-crowded
* typing experience.
*/
editor.renderer.setScrollMargin(
EDITOR.SCROLL_MARGIN_TOP_PX,
EDITOR.SCROLL_MARGIN_BOTTOM_PX,
0,
0
);
editor.setOptions({
highlightActiveLine: false,
highlightGutterLine: false,
minLines,
maxLines
});
editor.$blockScrolling = Infinity;
}

View file

@ -1,57 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { applyEditorOptions } from './apply_editor_options';
import { EDITOR } from '../../../common/constants';
describe('applyEditorOptions', () => {
let editor;
let setUseWrapMode;
let setScrollMargin;
let setOptions;
beforeEach(() => {
setUseWrapMode = jest.fn();
setScrollMargin = jest.fn();
setOptions = jest.fn();
editor = {
getSession: () => {
return { setUseWrapMode };
},
renderer: {
setScrollMargin,
},
setOptions,
};
});
it('creates default props and given line sizes', () => {
const minLines = 14;
const maxLines = 90;
applyEditorOptions(editor, minLines, maxLines);
expect(setUseWrapMode.mock.calls).toHaveLength(1);
expect(setUseWrapMode.mock.calls[0][0]).toBe(true);
expect(setScrollMargin.mock.calls).toHaveLength(1);
expect(setScrollMargin.mock.calls[0][0]).toEqual(EDITOR.SCROLL_MARGIN_TOP_PX);
expect(setScrollMargin.mock.calls[0][1]).toEqual(EDITOR.SCROLL_MARGIN_BOTTOM_PX);
expect(setScrollMargin.mock.calls[0][2]).toEqual(0);
expect(setScrollMargin.mock.calls[0][3]).toEqual(0);
expect(setOptions.mock.calls).toHaveLength(1);
expect(setOptions.mock.calls[0][0]).toEqual({
highlightActiveLine: false,
highlightGutterLine: false,
minLines: 14,
maxLines: 90,
});
expect(editor.$blockScrolling).toEqual(Infinity);
});
});

View file

@ -5,4 +5,3 @@
*/
export { GrokMode } from './grok_mode';
export { applyEditorOptions } from './apply_editor_options';

View file

@ -1,38 +0,0 @@
<form novalidate>
<toggle-panel
toggle-panel-id="action"
button-text="Custom Patterns"
is-collapsed="customPatternsInput.isSectionCollapsed('action')"
on-toggle="customPatternsInput.onSectionToggle"
data-test-subj="btnToggleCustomPatternsInput"
>
<div class="kuiFormSection">
<div class="kuiInfoPanel kuiInfoPanel--info kuiVerticalRhythm">
<div class="kuiInfoPanelHeader">
<span class="kuiInfoPanelHeader__icon kuiIcon kuiIcon--info fa-info"></span>
<span class="kuiInfoPanelHeader__title">
Enter one custom pattern per line. For example:
</span>
</div>
<div class="kuiInfoPanelBody">
<div class="kuiInfoPanelBody__message">
<pre><code>POSTFIX_QUEUEID [0-9A-F]{10,11}
MSG message-id=<%{GREEDYDATA}></code></pre>
</div>
</div>
</div>
<div class="grokdebugger-ace-editor">
<div
class="custom-patterns-input-editor kuiVerticalRhythm"
require-keys="true"
ui-ace="{
onLoad: aceLoaded
}"
ng-model="customPatternsInput.customPatterns"
data-test-subj="aceCustomPatternsInput"
></div>
</div>
</div>
</toggle-panel>
</form>

View file

@ -4,47 +4,59 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { uiModules } from 'ui/modules';
import { InitAfterBindingsWorkaround } from 'ui/compat';
import React from 'react';
import {
EuiAccordion,
EuiCallOut,
EuiCodeBlock,
EuiFormRow,
EuiPanel,
EuiCodeEditor,
EuiSpacer
} from '@elastic/eui';
import { EDITOR } from '../../../../../common/constants';
import { applyEditorOptions } from '../../../../lib/ace';
import template from './custom_patterns_input.html';
import './custom_patterns_input.less';
import 'ui/toggle_panel';
import 'ace';
const app = uiModules.get('xpack/grokdebugger');
export function CustomPatternsInput({ value, onChange }) {
const sampleCustomPatterns = `POSTFIX_QUEUEID [0-9A-F]{10,11}
MSG message-id=<%{GREEDYDATA}>`;
app.directive('customPatternsInput', function () {
return {
restrict: 'E',
template: template,
scope: {
onChange: '='
},
bindToController: true,
controllerAs: 'customPatternsInput',
controller: class CustomPatternsInputController extends InitAfterBindingsWorkaround {
initAfterBindings($scope) {
this.isCollapsed = {
action: true
};
$scope.$watch('customPatternsInput.customPatterns', () => {
this.onChange(this.customPatterns);
});
$scope.aceLoaded = (editor) => {
this.editor = editor;
applyEditorOptions(editor, EDITOR.PATTERN_MIN_LINES, EDITOR.PATTERN_MAX_LINES);
};
}
return (
<EuiAccordion
id="customPatternsInput"
buttonContent="Custom Patterns"
data-test-subj="btnToggleCustomPatternsInput"
>
onSectionToggle = (sectionId) => {
this.isCollapsed[sectionId] = !this.isCollapsed[sectionId];
}
<EuiSpacer size="m" />
isSectionCollapsed = (sectionId) => {
return this.isCollapsed[sectionId];
}
}
};
});
<EuiCallOut
title="Enter one custom pattern per line. For example:"
>
<EuiCodeBlock>
{ sampleCustomPatterns }
</EuiCodeBlock>
</EuiCallOut>
<EuiSpacer size="m" />
<EuiFormRow
fullWidth
data-test-subj="aceCustomPatternsInput"
>
<EuiPanel paddingSize="s">
<EuiCodeEditor
width="100%"
value={value}
onChange={onChange}
setOptions={{
highlightActiveLine: false,
highlightGutterLine: false,
minLines: EDITOR.PATTERN_MIN_LINES,
maxLines: EDITOR.PATTERN_MAX_LINES,
}}
/>
</EuiPanel>
</EuiFormRow>
</EuiAccordion>
);
}

View file

@ -1,5 +0,0 @@
custom-patterns-input {
.custom-patterns-input-editor {
height: 51px;
}
}

View file

@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
import './custom_patterns_input';
export { CustomPatternsInput } from './custom_patterns_input';

View file

@ -1,18 +0,0 @@
<form novalidate>
<div class="kuiFormSection">
<label class="kuiLabel kuiVerticalRhythmSmall">
Sample Data
</label>
<div class="grokdebugger-ace-editor">
<div
class="event-input-editor kuiVerticalRhythmSmall"
require-keys="true"
ui-ace="{
onLoad: aceLoaded
}"
ng-model="eventInput.rawEvent"
data-test-subj="aceEventInput"
></div>
</div>
</div>
</form>

View file

@ -4,34 +4,34 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { uiModules } from 'ui/modules';
import React from 'react';
import {
EuiFormRow,
EuiPanel,
EuiCodeEditor
} from '@elastic/eui';
import { EDITOR } from '../../../../../common/constants';
import { applyEditorOptions } from '../../../../lib/ace';
import template from './event_input.html';
import './event_input.less';
import 'ace';
const app = uiModules.get('xpack/grokdebugger');
app.directive('eventInput', function () {
return {
restrict: 'E',
template: template,
scope: {
onChange: '='
},
bindToController: true,
controllerAs: 'eventInput',
controller: class EventInputController {
constructor($scope) {
$scope.$watch('eventInput.rawEvent', (newRawEvent) => {
this.onChange(newRawEvent);
});
$scope.aceLoaded = (editor) => {
this.editor = editor;
applyEditorOptions(editor, EDITOR.SAMPLE_DATA_MIN_LINES, EDITOR.SAMPLE_DATA_MAX_LINES);
};
}
}
};
});
export function EventInput({ value, onChange }) {
return (
<EuiFormRow
label="Sample Data"
fullWidth
data-test-subj="aceEventInput"
>
<EuiPanel paddingSize="s">
<EuiCodeEditor
width="100%"
value={value}
onChange={onChange}
setOptions={{
highlightActiveLine: false,
highlightGutterLine: false,
minLines: EDITOR.SAMPLE_DATA_MIN_LINES,
maxLines: EDITOR.SAMPLE_DATA_MAX_LINES
}}
/>
</EuiPanel>
</EuiFormRow>
);
}

View file

@ -1,5 +0,0 @@
event-input {
.event-input-editor {
height: 51px;
}
}

View file

@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
import './event_input';
export { EventInput } from './event_input';

View file

@ -1,18 +0,0 @@
<form novalidate>
<div class="kuiFormSection">
<label class="kuiLabel kuiVerticalRhythmSmall">
Structured Data
</label>
<div
class="event-output-editor grokdebugger-ace-editor kuiVerticalRhythmSmall"
json-input
require-keys="true"
ui-ace="{
mode: 'json',
onLoad: aceLoaded
}"
ng-model="eventOutput.structuredEvent"
data-test-subj="aceEventOutput"
></div>
</div>
</form>

View file

@ -4,37 +4,33 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { uiModules } from 'ui/modules';
import template from './event_output.html';
import './event_output.less';
import 'ace';
import React from 'react';
import {
EuiFormRow,
EuiPanel,
EuiCodeEditor
} from '@elastic/eui';
const app = uiModules.get('xpack/grokdebugger');
app.directive('eventOutput', function () {
return {
restrict: 'E',
template: template,
scope: {
structuredEvent: '='
},
bindToController: true,
controllerAs: 'eventOutput',
controller: class EventOutputController {
constructor($scope) {
$scope.aceLoaded = (editor) => {
this.editor = editor;
editor.getSession().setUseWrapMode(true);
editor.setOptions({
readOnly: true,
export function EventOutput({ value }) {
return (
<EuiFormRow
label="Structured Data"
fullWidth
data-test-subj="aceEventOutput"
>
<EuiPanel paddingSize="s">
<EuiCodeEditor
mode="json"
isReadOnly
width="100%"
height="340px"
value={JSON.stringify(value, null, 2)}
setOptions={{
highlightActiveLine: false,
highlightGutterLine: false,
minLines: 20,
maxLines: 25
});
editor.$blockScrolling = Infinity;
};
}
}
};
});
}}
/>
</EuiPanel>
</EuiFormRow>
);
}

View file

@ -1,6 +0,0 @@
event-output {
.event-output-editor {
height: 340px;
padding-bottom: 10px;
}
}

View file

@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
import './event_output';
export { EventOutput } from './event_output';

View file

@ -0,0 +1,137 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import { isEmpty } from 'lodash';
import {
EuiForm,
EuiButton,
EuiPage,
EuiPageBody,
EuiPageContent,
EuiPageContentBody,
EuiSpacer
} from '@elastic/eui';
import { EventInput } from '../event_input';
import { PatternInput } from '../pattern_input';
import { CustomPatternsInput } from '../custom_patterns_input';
import { EventOutput } from '../event_output';
import { GrokdebuggerRequest } from '../../../../models/grokdebugger_request';
import { toastNotifications } from 'ui/notify';
export class GrokDebugger extends React.Component {
constructor(props) {
super(props);
this.state = {
rawEvent: '',
pattern: '',
customPatterns: '',
structuredEvent: {}
};
this.grokdebuggerRequest = new GrokdebuggerRequest();
}
onRawEventChange = (rawEvent) => {
this.setState({ rawEvent });
this.grokdebuggerRequest.rawEvent = rawEvent;
}
onPatternChange = (pattern) => {
this.setState({ pattern });
this.grokdebuggerRequest.pattern = pattern;
}
onCustomPatternsChange = (customPatterns) => {
this.setState({ customPatterns });
customPatterns = customPatterns.trim();
const customPatternsObj = {};
if (!customPatterns) {
this.grokdebuggerRequest.customPatterns = customPatternsObj;
return;
}
customPatterns.split('\n').forEach(customPattern => {
// Patterns are defined like so:
// patternName patternDefinition
// For example:
// POSTGRESQL %{DATESTAMP:timestamp} %{TZ} %{DATA:user_id} %{GREEDYDATA:connection_id} %{POSINT:pid}
const [ , patternName, patternDefinition ] = customPattern.match(/(\S+)\s+(.+)/) || [];
if (patternName && patternDefinition) {
customPatternsObj[patternName] = patternDefinition;
}
});
this.grokdebuggerRequest.customPatterns = customPatternsObj;
}
simulateGrok = async () => {
try {
const simulateResponse = await this.props.grokdebuggerService.simulate(this.grokdebuggerRequest);
this.setState({
structuredEvent: simulateResponse.structuredEvent
});
if (!isEmpty(simulateResponse.error)) {
toastNotifications.addDanger(simulateResponse.error);
}
} catch (e) {
toastNotifications.addDanger(e);
}
}
onSimulateClick = () => {
this.setState({
structuredEvent: {}
}, this.simulateGrok);
}
isSimulateDisabled = () => {
return this.state.rawEvent.trim() === ''
|| this.state.pattern.trim() === '';
}
render() {
return (
<EuiPage>
<EuiPageBody>
<EuiPageContent>
<EuiPageContentBody>
<EuiForm
className="grokdebugger-container"
data-test-subj="grokDebugger"
>
<EventInput
value={this.state.rawEvent}
onChange={this.onRawEventChange}
/>
<PatternInput
value={this.state.pattern}
onChange={this.onPatternChange}
/>
<CustomPatternsInput
value={this.state.customPatterns}
onChange={this.onCustomPatternsChange}
/>
<EuiSpacer />
<EuiButton
fill
onClick={this.onSimulateClick}
isDisabled={this.isSimulateDisabled()}
data-test-subj="btnSimulate"
>
Simulate
</EuiButton>
<EuiSpacer />
<EventOutput value={this.state.structuredEvent} />
</EuiForm>
</EuiPageContentBody>
</EuiPageContent>
</EuiPageBody>
</EuiPage>
);
}
}

View file

@ -0,0 +1,7 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export { GrokDebugger } from './grok_debugger';

View file

@ -1,23 +0,0 @@
<kbn-dev-tools-app class="grokdebuggerDevTool">
<div class="kuiViewContent kuiViewContent--constrainedWidth kuiViewContentItem">
<div
class="grokdebugger-container"
data-test-subj="grokDebugger"
>
<event-input on-change="grokdebugger.onRawEventChange"></event-input>
<pattern-input on-change="grokdebugger.onPatternChange"></pattern-input>
<custom-patterns-input on-change="grokdebugger.onCustomPatternsChange"></custom-patterns-input>
<div class="grokdebugger-simulate-button">
<button
class="kuiButton kuiButton--primary"
ng-disabled="!grokdebugger.isSimulateEnabled"
ng-click="grokdebugger.onSimulateClick()"
data-test-subj="btnSimulate"
>
Simulate
</button>
</div>
<event-output structured-event="grokdebugger.structuredEvent"></event-output>
</div>
</div>
</kbn-dev-tools-app>

View file

@ -1,87 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { uiModules } from 'ui/modules';
import template from './grokdebugger.html';
import { Notifier } from 'ui/notify';
import { GrokdebuggerRequest } from 'plugins/grokdebugger/models/grokdebugger_request';
import 'plugins/grokdebugger/services/grokdebugger';
import './grokdebugger.less';
import '../event_input';
import '../event_output';
import '../pattern_input';
import '../custom_patterns_input';
import { isEmpty, trim } from 'lodash';
const app = uiModules.get('xpack/grokdebugger');
app.directive('grokdebugger', function ($injector) {
const grokdebuggerService = $injector.get('grokdebuggerService');
return {
restrict: 'E',
template: template,
bindToController: true,
controllerAs: 'grokdebugger',
controller: class GrokdebuggerController {
constructor() {
this.structuredEvent = {};
this.grokdebuggerRequest = new GrokdebuggerRequest();
this.notifier = new Notifier({ location: 'GrokDebugger' });
}
onSimulateClick = () => {
return grokdebuggerService.simulate(this.grokdebuggerRequest)
.then(simulateResponse => {
this.structuredEvent = simulateResponse.structuredEvent;
// this error block is for responses which are 200, but still contain
// a grok debugger error like pattern not matched.
if (!isEmpty(simulateResponse.error)) {
this.notifier.error(simulateResponse.error);
}
})
.catch(e => {
// this error is for 4xx and 5xx responses
this.notifier.error(e);
});
}
onCustomPatternsChange = (customPatterns = '') => {
customPatterns = customPatterns.trim();
if (!customPatterns) {
return;
}
const customPatternsObj = {};
customPatterns.split('\n').forEach(customPattern => {
// Patterns are defined like so:
// patternName patternDefinition
// For example:
// POSTGRESQL %{DATESTAMP:timestamp} %{TZ} %{DATA:user_id} %{GREEDYDATA:connection_id} %{POSINT:pid}
const [ , patternName, patternDefinition ] = customPattern.match(/(\S+)\s+(.+)/) || [];
if (patternName && patternDefinition) {
customPatternsObj[patternName] = patternDefinition;
}
});
this.grokdebuggerRequest.customPatterns = customPatternsObj;
}
onRawEventChange = (rawEvent) => {
this.grokdebuggerRequest.rawEvent = rawEvent;
}
onPatternChange = (pattern) => {
this.grokdebuggerRequest.pattern = pattern;
}
get isSimulateEnabled() {
return !(isEmpty(trim(this.grokdebuggerRequest.rawEvent)) ||
isEmpty(trim(this.grokdebuggerRequest.pattern)));
}
}
};
});

View file

@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
import './pattern_input';
export { PatternInput } from './pattern_input';

View file

@ -1,18 +0,0 @@
<form novalidate>
<div class="kuiFormSection">
<label class="kuiLabel kuiVerticalRhythmSmall">
Grok Pattern
</label>
<div class="grokdebugger-ace-editor">
<div
class="pattern-input-editor kuiVerticalRhythmSmall"
require-keys="true"
ui-ace="{
onLoad: aceLoaded
}"
ng-model="patternInput.pattern"
data-test-subj="acePatternInput"
></div>
</div>
</div>
</form>

View file

@ -4,37 +4,36 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { uiModules } from 'ui/modules';
import { EDITOR } from '../../../../../common/constants';
import template from './pattern_input.html';
import './pattern_input.less';
import React from 'react';
import {
applyEditorOptions,
GrokMode
} from '../../../../lib/ace';
EuiFormRow,
EuiPanel,
EuiCodeEditor
} from '@elastic/eui';
import { EDITOR } from '../../../../../common/constants';
import { GrokMode } from '../../../../lib/ace';
const app = uiModules.get('xpack/grokdebugger');
app.directive('patternInput', function () {
return {
restrict: 'E',
template: template,
scope: {
onChange: '='
},
bindToController: true,
controllerAs: 'patternInput',
controller: class PatternInputController {
constructor($scope) {
$scope.$watch('patternInput.pattern', (newPattern) => {
this.onChange(newPattern);
});
$scope.aceLoaded = (editor) => {
this.editor = editor;
applyEditorOptions(editor, EDITOR.PATTERN_MIN_LINES, EDITOR.PATTERN_MAX_LINES);
editor.getSession().setMode(new GrokMode());
};
}
}
};
});
export function PatternInput({ value, onChange }) {
return (
<EuiFormRow
label="Grok Pattern"
fullWidth
data-test-subj="acePatternInput"
>
<EuiPanel paddingSize="s">
<EuiCodeEditor
width="100%"
value={value}
onChange={onChange}
mode={new GrokMode()}
setOptions={{
highlightActiveLine: false,
highlightGutterLine: false,
minLines: EDITOR.PATTERN_MIN_LINES,
maxLines: EDITOR.PATTERN_MAX_LINES,
}}
/>
</EuiPanel>
</EuiFormRow>
);
}

View file

@ -1,5 +0,0 @@
pattern-input {
.pattern-input-editor {
height: 51px;
}
}

View file

@ -0,0 +1,25 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { uiModules } from 'ui/modules';
import 'plugins/grokdebugger/services/grokdebugger';
import { GrokDebugger } from '../../components/grok_debugger';
import { render } from 'react-dom';
import React from 'react';
import './grokdebugger.less';
const app = uiModules.get('xpack/grokdebugger');
app.directive('grokdebugger', function ($injector) {
const grokdebuggerService = $injector.get('grokdebuggerService');
return {
restrict: 'E',
link: (scope, el) => {
render(<GrokDebugger grokdebuggerService={grokdebuggerService} />, el[0]);
}
};
});

View file

@ -3,22 +3,6 @@
@import (reference) "~ui/styles/theme";
grokdebugger {
.grokdebugger-container {
font-size: 16px;
}
.ace_editor {
font-size: 13px;
}
.grokdebugger-ace-editor {
border: 2px solid @kibanaGray5;
}
.grokdebugger-simulate-button {
margin-bottom: 10px;
}
.ace_grokStart,
.ace_grokEnd,
.ace_grokSeparator,

View file

@ -1 +1,3 @@
<grokdebugger></grokdebugger>
<kbn-dev-tools-app class="grokdebuggerDevTool">
<grokdebugger></grokdebugger>
</kbn-dev-tools-app>

View file

@ -8,7 +8,7 @@ import routes from 'ui/routes';
import { toastNotifications } from 'ui/notify';
import { XPackInfoProvider } from 'plugins/xpack_main/services/xpack_info';
import template from './grokdebugger_route.html';
import './components/grokdebugger';
import './directives/grokdebugger';
routes
.when('/dev_tools/grokdebugger', {

View file

@ -14,10 +14,10 @@ export function GrokDebuggerProvider({ getService }) {
// test subject selectors
const SUBJ_CONTAINER = 'grokDebugger';
const SUBJ_UI_ACE_EVENT_INPUT = `${SUBJ_CONTAINER} aceEventInput`;
const SUBJ_UI_ACE_PATTERN_INPUT = `${SUBJ_CONTAINER} acePatternInput`;
const SUBJ_UI_ACE_CUSTOM_PATTERNS_INPUT = `${SUBJ_CONTAINER} aceCustomPatternsInput`;
const SUBJ_UI_ACE_EVENT_OUTPUT = `${SUBJ_CONTAINER} aceEventOutput`;
const SUBJ_UI_ACE_EVENT_INPUT = `${SUBJ_CONTAINER} aceEventInput codeEditorContainer`;
const SUBJ_UI_ACE_PATTERN_INPUT = `${SUBJ_CONTAINER} acePatternInput codeEditorContainer`;
const SUBJ_UI_ACE_CUSTOM_PATTERNS_INPUT = `${SUBJ_CONTAINER} aceCustomPatternsInput codeEditorContainer`;
const SUBJ_UI_ACE_EVENT_OUTPUT = `${SUBJ_CONTAINER} aceEventOutput codeEditorContainer`;
const SUBJ_BTN_TOGGLE_CUSTOM_PATTERNS_INPUT = `${SUBJ_CONTAINER} btnToggleCustomPatternsInput`;
const SUBJ_BTN_SIMULATE = `${SUBJ_CONTAINER} btnSimulate`;