-
Notifications
You must be signed in to change notification settings - Fork 77
Adding functionality to associate existing detector with a visualization #484
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
2b74e3f
bfb9c69
7e24cd9
bcaa084
1a28212
fa45fd8
15dc68d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -80,19 +80,34 @@ import { FeatureAccordion } from '../../../../public/pages/ConfigureModel/compon | |
| import { | ||
| AD_DOCS_LINK, | ||
| AD_HIGH_CARDINALITY_LINK, | ||
| ALERTING_PLUGIN_NAME, | ||
| DEFAULT_SHINGLE_SIZE, | ||
| MAX_FEATURE_NUM, | ||
| } from '../../../../public/utils/constants'; | ||
| import { getNotifications } from '../../../../public/services'; | ||
| import { getNotifications, getUiActions } from '../../../../public/services'; | ||
| import { prettifyErrorMessage } from '../../../../server/utils/helpers'; | ||
| import { | ||
| ORIGIN_PLUGIN_VIS_LAYER, | ||
| OVERLAY_ANOMALIES, | ||
| VIS_LAYER_PLUGIN_TYPE, | ||
| } from '../../../../public/expressions/constants'; | ||
| import { formikToDetectorName, visFeatureListToFormik } from './helpers'; | ||
| import { AssociateExisting } from './AssociateExisting'; | ||
| import { mountReactNode } from '../../../../../../src/core/public/utils'; | ||
| import { CoreServicesContext } from '../../../../public/components/CoreServices/CoreServices'; | ||
| import { CoreStart } from '../../../../../../src/core/public'; | ||
|
|
||
| function AddAnomalyDetector({ embeddable, closeFlyout, mode, setMode }) { | ||
| function AddAnomalyDetector({ | ||
| embeddable, | ||
| closeFlyout, | ||
| mode, | ||
| setMode, | ||
| selectedDetector, | ||
| setSelectedDetector, | ||
| }) { | ||
| const dispatch = useDispatch(); | ||
| const core = React.useContext(CoreServicesContext) as CoreStart; | ||
|
|
||
| const [queryText, setQueryText] = useState(''); | ||
| useEffect(() => { | ||
| const getInitialIndices = async () => { | ||
|
|
@@ -148,21 +163,43 @@ function AddAnomalyDetector({ embeddable, closeFlyout, mode, setMode }) { | |
| } | ||
| }; | ||
|
|
||
| const handleSubmit = (formikProps) => { | ||
| const getAugmentVisSavedObject = (detectorId: string) => { | ||
| const fn = { | ||
| type: VisLayerTypes.PointInTimeEvents, | ||
| name: OVERLAY_ANOMALIES, | ||
| args: { | ||
| detectorId: detectorId, | ||
| }, | ||
| } as VisLayerExpressionFn; | ||
|
|
||
| const pluginResource = { | ||
| type: VIS_LAYER_PLUGIN_TYPE, | ||
| id: detectorId, | ||
| } as ISavedPluginResource; | ||
|
|
||
| return { | ||
| title: embeddable.vis.title, | ||
| originPlugin: ORIGIN_PLUGIN_VIS_LAYER, | ||
| pluginResource: pluginResource, | ||
| visId: embeddable.vis.id, | ||
| visLayerExpressionFn: fn, | ||
| } as ISavedAugmentVis; | ||
|
ohltyler marked this conversation as resolved.
|
||
| }; | ||
|
|
||
| //DONE 1. if detector is created succesfully, started succesfully and associated succesfully and alerting exists -> show end message with alerting button | ||
| //DONE 2. If detector is created succesfully, started succesfully and associated succesfully and alerting doesn't exist -> show end message with OUT alerting button | ||
| //DONE 3. If detector is created succesfully, started succesfully and fails association -> show one toast with detector created and started succesfully and one toast with failed association | ||
| //DONE 4. If detector is created succesfully, fails starting and fails association -> show one toast with detector created succesfully, one toast with failed association | ||
| //DONE 5. If detector is created successfully, fails starting and fails associating -> show one toast with detector created succesfully, one toast with fail starting, one toast with failed association | ||
| //DONE 6. If detector fails creating -> show one toast with detector failed creating | ||
| const handleSubmit = async (formikProps) => { | ||
| formikProps.setSubmitting(true); | ||
| try { | ||
| const detectorToCreate = formikToDetector(formikProps.values); | ||
| dispatch(createDetector(detectorToCreate)) | ||
| .then(async (response) => { | ||
| notifications.toasts.addSuccess( | ||
| `Detector created: ${formikProps.values.name}` | ||
| ); | ||
| dispatch(startDetector(response.response.id)) | ||
| .then((startDetectorResponse) => { | ||
| notifications.toasts.addSuccess( | ||
| `Successfully started the real-time detector` | ||
| ); | ||
| }) | ||
| .then((startDetectorResponse) => {}) | ||
| .catch((err: any) => { | ||
| notifications.toasts.addDanger( | ||
| prettifyErrorMessage( | ||
|
|
@@ -174,34 +211,54 @@ function AddAnomalyDetector({ embeddable, closeFlyout, mode, setMode }) { | |
| ); | ||
| }); | ||
|
|
||
| const fn = { | ||
| type: VisLayerTypes.PointInTimeEvents, | ||
| name: OVERLAY_ANOMALIES, | ||
| args: { | ||
| detectorId: response.response.id, | ||
| }, | ||
| } as VisLayerExpressionFn; | ||
|
|
||
| const pluginResource = { | ||
| type: VIS_LAYER_PLUGIN_TYPE, | ||
| id: response.response.id, | ||
| } as ISavedPluginResource; | ||
|
|
||
| const savedObjectToCreate = { | ||
| title: embeddable.vis.title, | ||
| originPlugin: ORIGIN_PLUGIN_VIS_LAYER, | ||
| pluginResource: pluginResource, | ||
| visId: embeddable.vis.id, | ||
| savedObjectType: 'visualization', | ||
| visLayerExpressionFn: fn, | ||
| } as ISavedAugmentVis; | ||
|
|
||
| // TODO: catch saved object failure | ||
| const savedObject = await createAugmentVisSavedObject( | ||
| savedObjectToCreate | ||
| ); | ||
|
|
||
| const saveObjectResponse = await savedObject.save({}); | ||
| const detectorId = response.response.id; | ||
|
|
||
| const augmentVisSavedObjectToCreate: ISavedAugmentVis = | ||
| getAugmentVisSavedObject(detectorId); | ||
|
|
||
| createAugmentVisSavedObject(augmentVisSavedObjectToCreate) | ||
| .then((savedObject: any) => { | ||
| savedObject | ||
| .save({}) | ||
| .then((response: any) => { | ||
| const shingleSize = get( | ||
| formikProps.values, | ||
| 'shingleSize', | ||
| DEFAULT_SHINGLE_SIZE | ||
| ); | ||
| const detectorId = get(savedObject, 'pluginResource.id', ''); | ||
| notifications.toasts.addSuccess({ | ||
| title: `The ${formikProps.values.name} is associated with the ${title} visualization`, | ||
| text: mountReactNode( | ||
| getEverythingSuccesfulButton(detectorId, shingleSize) | ||
| ), | ||
| }); | ||
| closeFlyout(); | ||
| }) | ||
| .catch((error) => { | ||
| console.error( | ||
| `Error associating selected detector4: ${error}` | ||
|
amitgalitz marked this conversation as resolved.
Outdated
|
||
| ); | ||
| notifications.toasts.addDanger( | ||
| prettifyErrorMessage( | ||
| `Error associating selected detector in save process: ${error}` | ||
| ) | ||
| ); | ||
| notifications.toasts.addSuccess( | ||
| `Detector created: ${formikProps.values.name}` | ||
| ); | ||
| }); | ||
| }) | ||
| .catch((error) => { | ||
| notifications.toasts.addDanger( | ||
| prettifyErrorMessage( | ||
| `Error associating selected detector3 in crate process: ${error}` | ||
|
amitgalitz marked this conversation as resolved.
Outdated
|
||
| ) | ||
| ); | ||
| notifications.toasts.addSuccess( | ||
| `Detector created: ${formikProps.values.name}` | ||
| ); | ||
| }); | ||
| }) | ||
| .catch((err: any) => { | ||
| dispatch(getDetectorCount()).then((response: any) => { | ||
|
|
@@ -231,6 +288,74 @@ function AddAnomalyDetector({ embeddable, closeFlyout, mode, setMode }) { | |
| } | ||
| }; | ||
|
|
||
| const getEverythingSuccesfulButton = (detectorId, shingleSize) => { | ||
|
amitgalitz marked this conversation as resolved.
Outdated
|
||
| return ( | ||
| <EuiText> | ||
| <p> | ||
| `Attempting to initialize the detector with historical data. This | ||
| initializing process takes approximately 1 minute if you have data in | ||
| each of the last ${32 + shingleSize} consecutive intervals.` | ||
| </p> | ||
| {alertingExists(detectorId) ? ( | ||
| <EuiFlexItem> | ||
| <EuiButton onClick={() => openAlerting(detectorId)}> | ||
| Set Up Alerts | ||
| </EuiButton>{' '} | ||
| <p>set up alerts</p> | ||
| </EuiFlexItem> | ||
| ) : null} | ||
| </EuiText> | ||
| ); | ||
| }; | ||
|
|
||
| const alertingExists = (detectorId) => { | ||
| try { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we have a setup alert button on existing AD detector overview page, is this how we currently check if alerting exist? also what does
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We actually don't have this logic on the setup alert button in AD overview page. If there is no alerting plugin, the button still shows and it just sends to a broken page.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I believe we used to have a check here. Regardless, this is bad UX. Can you open an issue on that. We can probably keep it broad, like "clean up how to detect alerting plugin is installed"
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Opened an issue #493 |
||
| const uiActionService = getUiActions(); | ||
| uiActionService.getTrigger('ALERTING_TRIGGER_AD_ID'); | ||
| return true; | ||
| } catch (e) { | ||
| console.error('No allerting trigger exists', e); | ||
|
amitgalitz marked this conversation as resolved.
Outdated
|
||
| return false; | ||
| } | ||
| }; | ||
|
|
||
| const openAlerting = (detectorId) => { | ||
| const uiActionService = getUiActions(); | ||
| uiActionService | ||
| .getTrigger('ALERTING_TRIGGER_AD_ID') | ||
| .exec({ embeddable, detectorId }); | ||
| }; | ||
|
|
||
| const handleAssociate = async (detector: DetectorListItem) => { | ||
| const augmentVisSavedObjectToCreate: ISavedAugmentVis = | ||
| getAugmentVisSavedObject(detector.id); | ||
|
|
||
| createAugmentVisSavedObject(augmentVisSavedObjectToCreate) | ||
| .then((savedObject: any) => { | ||
| savedObject | ||
| .save({}) | ||
| .then((response: any) => { | ||
| notifications.toasts.addSuccess({ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here's a way to make the toast wider:
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you, made the fix |
||
| title: `The ${detector.name} is associated with the ${title} visualization`, | ||
| text: "The detector's anomalies do not appear on the visualization. Refresh your dashboard to update the visualization", | ||
| }); | ||
| closeFlyout(); | ||
| }) | ||
| .catch((error) => { | ||
| notifications.toasts.addDanger( | ||
| prettifyErrorMessage( | ||
| `Error associating selected detector: ${error}` | ||
| ) | ||
| ); | ||
| }); | ||
| }) | ||
| .catch((error) => { | ||
| notifications.toasts.addDanger( | ||
| prettifyErrorMessage(`Error associating selected detector: ${error}`) | ||
| ); | ||
| }); | ||
| }; | ||
|
|
||
| const validateVisDetectorName = async (detectorName: string) => { | ||
| if (isEmpty(detectorName)) { | ||
| return 'Detector name cannot be empty'; | ||
|
|
@@ -325,6 +450,13 @@ function AddAnomalyDetector({ embeddable, closeFlyout, mode, setMode }) { | |
| ))} | ||
| </EuiFormFieldset> | ||
| <EuiSpacer size="m" /> | ||
| {mode === 'existing' && ( | ||
| <AssociateExisting | ||
| embeddableVisId={embeddable.vis.id} | ||
| selectedDetector={selectedDetector} | ||
| setSelectedDetector={setSelectedDetector} | ||
| ></AssociateExisting> | ||
| )} | ||
| {mode === 'create' && ( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to the conditional on line 830, we can do the same here for these 2 exclusive scenarios.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. mode can also be 'associated'
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the difference between
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. existing is the one with the button to associate an existing detector flyout and associated is the flyout with the list of all currently associated detectors with ability to unlink. I can add some comments and constants, will do that in my final commit after fixing the dependency issue |
||
| <div className="create-new"> | ||
| <EuiText size="xs"> | ||
|
|
@@ -695,16 +827,27 @@ function AddAnomalyDetector({ embeddable, closeFlyout, mode, setMode }) { | |
| <EuiButtonEmpty onClick={closeFlyout}>Cancel</EuiButtonEmpty> | ||
| </EuiFlexItem> | ||
| <EuiFlexItem grow={false}> | ||
| <EuiButton | ||
| fill={true} | ||
| data-test-subj="adAnywhereCreateDetectorButton" | ||
| isLoading={formikProps.isSubmitting} | ||
| onClick={() => { | ||
| handleValidationAndSubmit(formikProps); | ||
| }} | ||
| > | ||
| Create Detector | ||
| </EuiButton> | ||
| {mode === 'existing' ? ( | ||
| <EuiButton | ||
| fill={true} | ||
| data-test-subj="adAnywhereCreateDetectorButton" | ||
| isLoading={formikProps.isSubmitting} | ||
| onClick={() => handleAssociate(selectedDetector)} | ||
| > | ||
| associate detector | ||
|
amitgalitz marked this conversation as resolved.
Outdated
|
||
| </EuiButton> | ||
| ) : ( | ||
| <EuiButton | ||
| fill={true} | ||
| data-test-subj="adAnywhereCreateDetectorButton" | ||
| isLoading={formikProps.isSubmitting} | ||
| onClick={() => { | ||
| handleValidationAndSubmit(formikProps); | ||
| }} | ||
| > | ||
| create detector | ||
|
amitgalitz marked this conversation as resolved.
Outdated
|
||
| </EuiButton> | ||
| )} | ||
| </EuiFlexItem> | ||
| </EuiFlexGroup> | ||
| </EuiFlyoutFooter> | ||
|
|
||

Uh oh!
There was an error while loading. Please reload this page.