-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Adds an option to switch to an advanced (JSON) editor when creating an analytics job. This builds upon the previous work for the modal for analytics job creation and the use of useReducer(): - The files of the custom hook useCreateAnalyticsForm() have been further split up and there's now separate actions.ts and state.ts files. - To only allow updating what's really related to the form value's state via setFormState, the state structure has been updated and more fine grained actions have been added. - The user can enabled the advanced editor, but cannot move back to the original form (there's a help text in the UI about that). - The advanced editor component's (CreateAnalyticsAdvancedEditor) structure is based on the regular form, it still has an input field for the job ID and the toggle for optionally creating an index pattern. The fields for source/destination index are replaced by an editable JSON textarea input. - The advanced editor features mostly the same validation like the regular form. For example, if the source index isn't valid, an error will be shown in a CallOut below the editable area.
- Loading branch information
Showing
18 changed files
with
750 additions
and
231 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
184 changes: 184 additions & 0 deletions
184
...nagement/components/create_analytics_advanced_editor/create_analytics_advanced_editor.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
/* | ||
* 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, { FC, Fragment } from 'react'; | ||
|
||
import { | ||
EuiCallOut, | ||
EuiCodeEditor, | ||
EuiFieldText, | ||
EuiForm, | ||
EuiFormRow, | ||
EuiSpacer, | ||
EuiSwitch, | ||
} from '@elastic/eui'; | ||
|
||
import { i18n } from '@kbn/i18n'; | ||
|
||
import { CreateAnalyticsFormProps } from '../../hooks/use_create_analytics_form'; | ||
|
||
export const CreateAnalyticsAdvancedEditor: FC<CreateAnalyticsFormProps> = ({ actions, state }) => { | ||
const { | ||
resetAdvancedEditorMessages, | ||
setAdvancedEditorRawString, | ||
setFormState, | ||
setJobConfig, | ||
} = actions; | ||
|
||
const { advancedEditorMessages, advancedEditorRawString, isJobCreated, requestMessages } = state; | ||
|
||
const { | ||
createIndexPattern, | ||
destinationIndexPatternTitleExists, | ||
jobId, | ||
jobIdEmpty, | ||
jobIdExists, | ||
jobIdValid, | ||
} = state.form; | ||
|
||
const onChange = (str: string) => { | ||
setAdvancedEditorRawString(str); | ||
try { | ||
setJobConfig(JSON.parse(str)); | ||
} catch (e) { | ||
resetAdvancedEditorMessages(); | ||
} | ||
}; | ||
|
||
return ( | ||
<EuiForm> | ||
{requestMessages.map((requestMessage, i) => ( | ||
<Fragment key={i}> | ||
<EuiCallOut | ||
title={requestMessage.message} | ||
color={requestMessage.error !== undefined ? 'danger' : 'primary'} | ||
iconType={requestMessage.error !== undefined ? 'alert' : 'checkInCircleFilled'} | ||
size="s" | ||
> | ||
{requestMessage.error !== undefined ? <p>{requestMessage.error}</p> : null} | ||
</EuiCallOut> | ||
<EuiSpacer size="s" /> | ||
</Fragment> | ||
))} | ||
{!isJobCreated && ( | ||
<Fragment> | ||
<EuiFormRow | ||
label={i18n.translate('xpack.ml.dataframe.analytics.create.advancedEditor.jobIdLabel', { | ||
defaultMessage: 'Analytics job ID', | ||
})} | ||
isInvalid={(!jobIdEmpty && !jobIdValid) || jobIdExists} | ||
error={[ | ||
...(!jobIdEmpty && !jobIdValid | ||
? [ | ||
i18n.translate( | ||
'xpack.ml.dataframe.analytics.create.advancedEditor.jobIdInvalidError', | ||
{ | ||
defaultMessage: | ||
'Must contain lowercase alphanumeric characters (a-z and 0-9), hyphens, and underscores only and must start and end with alphanumeric characters.', | ||
} | ||
), | ||
] | ||
: []), | ||
...(jobIdExists | ||
? [ | ||
i18n.translate( | ||
'xpack.ml.dataframe.analytics.create.advancedEditor.jobIdExistsError', | ||
{ | ||
defaultMessage: 'An analytics job with this ID already exists.', | ||
} | ||
), | ||
] | ||
: []), | ||
]} | ||
> | ||
<EuiFieldText | ||
disabled={isJobCreated} | ||
placeholder="analytics job ID" | ||
value={jobId} | ||
onChange={e => setFormState({ jobId: e.target.value })} | ||
aria-label={i18n.translate( | ||
'xpack.ml.dataframe.analytics.create.advancedEditor.jobIdInputAriaLabel', | ||
{ | ||
defaultMessage: 'Choose a unique analytics job ID.', | ||
} | ||
)} | ||
isInvalid={(!jobIdEmpty && !jobIdValid) || jobIdExists} | ||
/> | ||
</EuiFormRow> | ||
|
||
<EuiFormRow | ||
label={i18n.translate( | ||
'xpack.ml.dataframe.analytics.create.advancedEditor.configRequestBody', | ||
{ | ||
defaultMessage: 'Configuration request body', | ||
} | ||
)} | ||
style={{ maxWidth: '100%' }} | ||
> | ||
<EuiCodeEditor | ||
mode="json" | ||
width="100%" | ||
value={advancedEditorRawString} | ||
onChange={onChange} | ||
setOptions={{ | ||
fontSize: '12px', | ||
}} | ||
aria-label={i18n.translate( | ||
'xpack.ml.dataframe.analytics.create.advancedEditor.codeEditorAriaLabel', | ||
{ | ||
defaultMessage: 'Advanced analytics job editor', | ||
} | ||
)} | ||
/> | ||
</EuiFormRow> | ||
{advancedEditorMessages.map((advancedEditorMessage, i) => ( | ||
<Fragment key={i}> | ||
<EuiCallOut | ||
title={ | ||
advancedEditorMessage.message !== '' | ||
? advancedEditorMessage.message | ||
: advancedEditorMessage.error | ||
} | ||
color={advancedEditorMessage.error !== undefined ? 'danger' : 'primary'} | ||
iconType={ | ||
advancedEditorMessage.error !== undefined ? 'alert' : 'checkInCircleFilled' | ||
} | ||
size="s" | ||
> | ||
{advancedEditorMessage.message !== '' && | ||
advancedEditorMessage.error !== undefined ? ( | ||
<p>{advancedEditorMessage.error}</p> | ||
) : null} | ||
</EuiCallOut> | ||
<EuiSpacer size="s" /> | ||
</Fragment> | ||
))} | ||
<EuiFormRow | ||
isInvalid={createIndexPattern && destinationIndexPatternTitleExists} | ||
error={ | ||
createIndexPattern && | ||
destinationIndexPatternTitleExists && [ | ||
i18n.translate('xpack.ml.dataframe.analytics.create.indexPatternTitleError', { | ||
defaultMessage: 'An index pattern with this title already exists.', | ||
}), | ||
] | ||
} | ||
> | ||
<EuiSwitch | ||
disabled={isJobCreated} | ||
name="mlDataFrameAnalyticsCreateIndexPattern" | ||
label={i18n.translate('xpack.ml.dataframe.analytics.create.createIndexPatternLabel', { | ||
defaultMessage: 'Create index pattern', | ||
})} | ||
checked={createIndexPattern === true} | ||
onChange={() => setFormState({ createIndexPattern: !createIndexPattern })} | ||
/> | ||
</EuiFormRow> | ||
</Fragment> | ||
)} | ||
</EuiForm> | ||
); | ||
}; |
7 changes: 7 additions & 0 deletions
7
...analytics/pages/analytics_management/components/create_analytics_advanced_editor/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 { CreateAnalyticsAdvancedEditor } from './create_analytics_advanced_editor'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.