Skip to content
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

Extract fatal notification into fatalError service, add support for EuiToast notifications #15749

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5b16537
Reorganize notify/lib files. Extract fatal notification into a fatalE…
cjcenizal Dec 21, 2017
25bde88
Import Notifier from ui/notify module.
cjcenizal Dec 21, 2017
2ebadc7
Convert notify/lib tests to use Jest.
cjcenizal Dec 22, 2017
45f4af1
Move kbn-notifications directive definition from directives.js to not…
cjcenizal Dec 22, 2017
4db5249
Remove kbn-notifications directive import from typeahead.
cjcenizal Dec 22, 2017
4a4943e
Add basic mechanism for surfacing toasts.
cjcenizal Dec 22, 2017
adc1de5
Use toast notifications in Dashboard.
cjcenizal Dec 22, 2017
88c3051
Use toast notifications in Visualize.
cjcenizal Dec 22, 2017
d3505f8
Use toast notifications in Management.
cjcenizal Dec 22, 2017
e8038b1
Extend toast lifetime to 6 seconds.
cjcenizal Dec 22, 2017
5ed6a71
Add tests for GlobalToastList.
cjcenizal Dec 22, 2017
b26000b
Update state error handling test to assert against thrown error inste…
cjcenizal Jan 5, 2018
3e8e8e6
Temporarily skip failing tests.
cjcenizal Jan 3, 2018
733070c
Use single quotation marks when referring to a full name of an object.
cjcenizal Jan 8, 2018
dd1e3a6
Fix tests.
cjcenizal Jan 5, 2018
ee107e3
Fix input control vis and markdown vis tests by configuring functiona…
cjcenizal Jan 10, 2018
a5ae513
Fix Dashboard save tests.
cjcenizal Jan 10, 2018
6c26726
Last minute polish.
cjcenizal Jan 10, 2018
18da564
Use Chris's more efficient syntax.
cjcenizal Jan 25, 2018
818612b
Add addSuccess, addWarning, and addDanger convenience methdos to Toas…
cjcenizal Jan 25, 2018
7763316
Update ToastNotifications to accept strings as well as objects.
cjcenizal Jan 25, 2018
9dede7d
Remove all use cases of notify.info. Replace missing indices banner n…
cjcenizal Jan 25, 2018
78bfe67
Remove notify.info method.
cjcenizal Jan 25, 2018
bf0f4bb
Auto-dismiss missingIndicesMessage after 15 seconds.
cjcenizal Jan 25, 2018
c37ae91
Rename missingIndicesMessage to createFirstIndexPatternPrompt.
cjcenizal Jan 25, 2018
cb568ae
Remove unit tests for notifier info method.
cjcenizal Jan 25, 2018
7472600
Fix Dashboard and Saved Search test.
cjcenizal Jan 26, 2018
13bbfc4
Fix bug with toast dismissal logic.
cjcenizal Jan 26, 2018
9c42f06
Update testSubjects.exists to accept a timeout argument.
cjcenizal Jan 26, 2018
6404ba6
Update toastNotifications.add to return the new toast.
cjcenizal Jan 26, 2018
81799fc
Add documentation on UI systems.
cjcenizal Jan 26, 2018
eaa1141
Change 'No index pattern' prompt to use warning color.
cjcenizal Jan 26, 2018
c89ad15
Fix discover functional tests.
cjcenizal Jan 26, 2018
fb7d9e4
Add note on functional test use cases to docs.
cjcenizal Jan 26, 2018
545589d
Improve structure of toast docs.
cjcenizal Jan 26, 2018
e036a2d
Increase functional test timeout to 3 minutes.
cjcenizal Jan 26, 2018
a990b0c
Skip some flaky tests.
cjcenizal Jan 27, 2018
a898367
Fix copy to clipboard tests.
cjcenizal Jan 27, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ out an open PR:

- [CONTRIBUTING.md](CONTRIBUTING.md) will help you get Kibana up and running.
- If you would like to contribute code, please follow our [STYLEGUIDE.md](STYLEGUIDE.md).
- Learn more about our UI code with [UI_SYSTEMS.md](src/ui/public/UI_SYSTEMS.md).
- For all other questions, check out the [FAQ.md](FAQ.md) and
[wiki](https://github.com/elastic/kibana/wiki).

Expand Down
15 changes: 12 additions & 3 deletions src/core_plugins/kibana/public/dashboard/dashboard_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import angular from 'angular';
import { uiModules } from 'ui/modules';
import chrome from 'ui/chrome';
import { applyTheme } from 'ui/theme';
import { toastNotifications } from 'ui/notify';

import 'ui/query_bar';

Expand Down Expand Up @@ -183,14 +184,18 @@ app.directive('dashboardApp', function ($injector) {
$scope.addVis = function (hit, showToast = true) {
dashboardStateManager.addNewPanel(hit.id, 'visualization');
if (showToast) {
notify.info(`Visualization successfully added to your dashboard`);
toastNotifications.addSuccess('Added visualization to your dashboard');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Visualization was added to your dashboard

}
};

$scope.addSearch = function (hit) {
dashboardStateManager.addNewPanel(hit.id, 'search');
notify.info(`Search successfully added to your dashboard`);
toastNotifications.addSuccess({
title: 'Added saved search to your dashboard',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saved search was added to your dashboard

'data-test-subj': 'addSavedSearchToDashboardSuccess',
});
};

$scope.$watch('model.hidePanelTitles', () => {
dashboardStateManager.setHidePanelTitles($scope.model.hidePanelTitles);
});
Expand Down Expand Up @@ -268,7 +273,11 @@ app.directive('dashboardApp', function ($injector) {
.then(function (id) {
$scope.kbnTopNav.close('save');
if (id) {
notify.info(`Saved Dashboard as "${dash.title}"`);
toastNotifications.addSuccess({
title: `Saved '${dash.title}'`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dashboard '${dash.title}' was saved

'data-test-subj': 'saveDashboardSuccess',
});

if (dash.id !== $routeParams.id) {
kbnUrl.change(createDashboardEditUrl(dash.id));
} else {
Expand Down
5 changes: 2 additions & 3 deletions src/core_plugins/kibana/public/dashboard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'plugins/kibana/dashboard/saved_dashboard/saved_dashboards';
import 'plugins/kibana/dashboard/styles/index.less';
import 'plugins/kibana/dashboard/dashboard_config';
import uiRoutes from 'ui/routes';
import { notify } from 'ui/notify';
import { toastNotifications } from 'ui/notify';

import dashboardTemplate from 'plugins/kibana/dashboard/dashboard_app.html';
import dashboardListingTemplate from './listing/dashboard_listing.html';
Expand Down Expand Up @@ -71,8 +71,7 @@ uiRoutes
if (error instanceof SavedObjectNotFound && id === 'create') {
// Note "new AppState" is neccessary so the state in the url is preserved through the redirect.
kbnUrl.redirect(DashboardConstants.CREATE_NEW_DASHBOARD_URL, {}, new AppState());
notify.error(
'The url "dashboard/create" is deprecated and will be removed in 6.0. Please update your bookmarks.');
toastNotifications.addWarning('The url "dashboard/create" was removed in 6.0. Please update your bookmarks.');
} else {
throw error;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import * as filterActions from 'ui/doc_table/actions/filter';
import dateMath from '@elastic/datemath';
import 'ui/doc_table';
import 'ui/visualize';
import 'ui/notify';
import 'ui/fixed_scroll';
import 'ui/directives/validate_json';
import 'ui/filters/moment';
Expand All @@ -16,6 +15,7 @@ import 'ui/state_management/app_state';
import 'ui/timefilter';
import 'ui/share';
import 'ui/query_bar';
import { toastNotifications } from 'ui/notify';
import { VisProvider } from 'ui/vis';
import { BasicResponseHandlerProvider } from 'ui/vis/response_handlers/basic';
import { DocTitleProvider } from 'ui/doc_title';
Expand Down Expand Up @@ -416,7 +416,11 @@ function discoverController(
$scope.kbnTopNav.close('save');

if (id) {
notify.info('Saved Data Source "' + savedSearch.title + '"');
toastNotifications.addSuccess({
title: `Saved '${savedSearch.title}'`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Data source "searchSearch.title" was saved

'data-test-subj': 'saveSearchSuccess',
});

if (savedSearch.id !== $route.current.params.id) {
kbnUrl.change('/discover/{{id}}', { id: savedSearch.id });
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/core_plugins/kibana/public/kibana.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import 'ui/vislib';
import 'ui/agg_response';
import 'ui/agg_types';
import 'ui/timepicker';
import { Notifier } from 'ui/notify/notifier';
import { Notifier } from 'ui/notify';
import 'leaflet';
import { KibanaRootController } from './kibana_root_controller';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import _ from 'lodash';
import { fatalError } from 'ui/notify';
import { IndexPatternMissingIndices } from 'ui/errors';
import 'ui/directives/validate_index_pattern';
import 'ui/directives/auto_select_if_only_one';
Expand Down Expand Up @@ -288,7 +289,7 @@ uiModules.get('apps/management')
return notify.error(`Couldn't locate any indices matching that pattern. Please add the index to Elasticsearch`);
}

notify.fatal(err);
fatalError(err);
}).finally(() => {
this.isCreatingIndexPattern = false;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import './scripted_field_editor';
import './source_filters_table';
import { KbnUrlProvider } from 'ui/url';
import { IndicesEditSectionsProvider } from './edit_sections';
import { fatalError } from 'ui/notify';
import uiRoutes from 'ui/routes';
import { uiModules } from 'ui/modules';
import template from './edit_index_pattern.html';
Expand Down Expand Up @@ -116,7 +117,7 @@ uiModules.get('apps/management')
.then(function () {
$location.url('/management/kibana/index');
})
.catch(notify.fatal);
.catch(fatalError);
}

const confirmModalOptions = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'ui/field_editor';
import { IndexPatternsFieldProvider } from 'ui/index_patterns/_field';
import { KbnUrlProvider } from 'ui/url';
import uiRoutes from 'ui/routes';
import { toastNotifications } from 'ui/notify';
import template from './scripted_field_editor.html';

uiRoutes
Expand Down Expand Up @@ -29,9 +30,8 @@ uiRoutes
}
},
controllerAs: 'fieldSettings',
controller: function FieldEditorPageController($route, Private, Notifier, docTitle) {
controller: function FieldEditorPageController($route, Private, docTitle) {
const Field = Private(IndexPatternsFieldProvider);
const notify = new Notifier({ location: 'Field Editor' });
const kbnUrl = Private(KbnUrlProvider);

this.mode = $route.current.mode;
Expand All @@ -43,7 +43,8 @@ uiRoutes
this.field = this.indexPattern.fields.byName[fieldName];

if (!this.field) {
notify.error(this.indexPattern + ' does not have a "' + fieldName + '" field.');
toastNotifications.add(`'${this.indexPattern.title}' index pattern doesn't have a scripted field called '${fieldName}'`);

kbnUrl.redirectToRoute(this.indexPattern, 'edit');
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@ import 'ui/paginated_table';
import fieldControlsHtml from '../field_controls.html';
import { dateScripts } from './date_scripts';
import { uiModules } from 'ui/modules';
import { toastNotifications } from 'ui/notify';
import template from './scripted_fields_table.html';
import { getSupportedScriptingLanguages, getDeprecatedScriptingLanguages } from 'ui/scripting_languages';
import { documentationLinks } from 'ui/documentation_links/documentation_links';

uiModules.get('apps/management')
.directive('scriptedFieldsTable', function (kbnUrl, Notifier, $filter, confirmModal) {
.directive('scriptedFieldsTable', function (kbnUrl, $filter, confirmModal) {
const rowScopes = []; // track row scopes, so they can be destroyed as needed
const filter = $filter('filter');

const notify = new Notifier();

return {
restrict: 'E',
template,
Expand Down Expand Up @@ -82,11 +81,17 @@ uiModules.get('apps/management')
});

if (fieldsAdded > 0) {
notify.info(fieldsAdded + ' script fields created');
toastNotifications.addSuccess({
title: 'Created script fields',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that maybe this should be "added" See the button guidelines for a description.
Also, the Kibana "Create Index" page uses "scripted field"

Recommendation:

Scripted field "fieldname" was added

or

Scripted field was added

Prefer one line over title and text

text: `Created ${fieldsAdded}`,
});
}

if (conflictFields.length > 0) {
notify.info('Not adding ' + conflictFields.length + ' duplicate fields: ' + conflictFields.join(', '));
toastNotifications.addWarning({
title: `Didn't add duplicate fields`,
text: `${conflictFields.length} fields: ${conflictFields.join(', ')}`,
});
}
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { find, each, escape, invoke, size, without } from 'lodash';

import { uiModules } from 'ui/modules';
import { Notifier } from 'ui/notify/notifier';
import { Notifier } from 'ui/notify';
import { FieldWildcardProvider } from 'ui/field_wildcard';

import controlsHtml from './controls.html';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,23 @@ import { savedObjectManagementRegistry } from 'plugins/kibana/management/saved_o
import objectViewHTML from 'plugins/kibana/management/sections/objects/_view.html';
import uiRoutes from 'ui/routes';
import { uiModules } from 'ui/modules';
import { fatalError, toastNotifications } from 'ui/notify';
import 'ui/accessibility/kbn_ui_ace_keyboard_mode';
import { castEsToKbnFieldTypeName } from '../../../../../../utils';
import { SavedObjectsClientProvider } from 'ui/saved_objects';

const location = 'SavedObject view';

uiRoutes
.when('/management/kibana/objects/:service/:id', {
template: objectViewHTML
});

uiModules.get('apps/management')
.directive('kbnManagementObjectsView', function (kbnIndex, Notifier, confirmModal) {
.directive('kbnManagementObjectsView', function (kbnIndex, confirmModal) {
return {
restrict: 'E',
controller: function ($scope, $injector, $routeParams, $location, $window, $rootScope, Private) {
const notify = new Notifier({ location: 'SavedObject view' });
const serviceObj = savedObjectManagementRegistry.get($routeParams.service);
const service = $injector.get(serviceObj.service);
const savedObjectsClient = Private(SavedObjectsClientProvider);
Expand Down Expand Up @@ -122,7 +124,7 @@ uiModules.get('apps/management')
return (orderIndex > -1) ? orderIndex : Infinity;
});
})
.catch(notify.fatal);
.catch(error => fatalError(error, location));

// This handles the validation of the Ace Editor. Since we don't have any
// other hooks into the editors to tell us if the content is valid or not
Expand Down Expand Up @@ -173,7 +175,7 @@ uiModules.get('apps/management')
.then(function () {
return redirectHandler('deleted');
})
.catch(notify.fatal);
.catch(error => fatalError(error, location));
}
const confirmModalOptions = {
onConfirm: doDelete,
Expand Down Expand Up @@ -207,18 +209,17 @@ uiModules.get('apps/management')
.then(function () {
return redirectHandler('updated');
})
.catch(notify.fatal);
.catch(error => fatalError(error, location));
};

function redirectHandler(action) {
const msg = 'You successfully ' + action + ' the "' + $scope.obj.attributes.title + '" ' + $scope.title.toLowerCase() + ' object';

$location.path('/management/kibana/objects').search({
_a: rison.encode({
tab: serviceObj.title
})
});
notify.info(msg);

toastNotifications.addSuccess(`${_.capitalize(action)} '${$scope.obj.attributes.title}' ${$scope.title.toLowerCase()} object`);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what this is supposed to say, but follow this format:

object type > object name > was/were > past tense action

}
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import 'ui/elastic_textarea';
import 'ui/filters/markdown';
import { uiModules } from 'ui/modules';
import { fatalError } from 'ui/notify';
import { keyCodes } from '@elastic/eui';
import advancedRowTemplate from 'plugins/kibana/management/sections/settings/advanced_row.html';

uiModules.get('apps/management')
.directive('advancedRow', function (config, Notifier) {
.directive('advancedRow', function (config) {
return {
restrict: 'A',
replace: true,
Expand All @@ -15,8 +16,6 @@ uiModules.get('apps/management')
configs: '='
},
link: function ($scope) {
const notify = new Notifier();

// To allow passing form validation state back
$scope.forms = {};

Expand All @@ -27,7 +26,7 @@ uiModules.get('apps/management')
.then(function () {
conf.loading = conf.editing = false;
})
.catch(notify.fatal);
.catch(fatalError);
};

$scope.maybeCancel = function ($event, conf) {
Expand Down
10 changes: 7 additions & 3 deletions src/core_plugins/kibana/public/visualize/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import 'ui/share';
import 'ui/query_bar';
import chrome from 'ui/chrome';
import angular from 'angular';
import { Notifier } from 'ui/notify/notifier';
import { Notifier, toastNotifications } from 'ui/notify';
import { VisTypesRegistryProvider } from 'ui/registry/vis_types';
import { DocTitleProvider } from 'ui/doc_title';
import { FilterBarQueryFilterProvider } from 'ui/filter_bar/query_filter';
Expand Down Expand Up @@ -251,7 +251,11 @@ function VisEditor($scope, $route, timefilter, AppState, $window, kbnUrl, courie
$scope.kbnTopNav.close('save');

if (id) {
notify.info('Saved Visualization "' + savedVis.title + '"');
toastNotifications.addSuccess({
title: `Saved '${savedVis.title}'`,
'data-test-subj': 'saveVisualizationSuccess',
});

if ($scope.isAddToDashMode()) {
const savedVisualizationParsedUrl = new KibanaParsedUrl({
basePath: chrome.getBasePath(),
Expand Down Expand Up @@ -281,7 +285,7 @@ function VisEditor($scope, $route, timefilter, AppState, $window, kbnUrl, courie
$scope.unlink = function () {
if (!$state.linked) return;

notify.info(`Unlinked Visualization "${savedVis.title}" from Saved Search "${savedVis.savedSearch.title}"`);
toastNotifications.addSuccess(`Unlinked from saved search '${savedVis.savedSearch.title}'`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Visualization "savedVis.title" was unlinked from saved search "savedSearch.title"

We need a better word for "unlinked"


$state.linked = false;
const parent = searchSource.getParent(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import labDisabledTemplate from './visualize_lab_disabled.html';
import chrome from 'ui/chrome';

export class VisualizeEmbeddableFactory extends EmbeddableFactory {
constructor(savedVisualizations, timefilter, Notifier, Promise, Private, config) {
constructor(savedVisualizations, timefilter, Promise, Private, config) {
super();
this._config = config;
this.savedVisualizations = savedVisualizations;
this.name = 'visualization';
this.Promise = Promise;
this.brushEvent = utilsBrushEventProvider(timefilter);
this.filterBarClickHandler = filterBarClickHandlerProvider(Notifier, Private);
this.filterBarClickHandler = filterBarClickHandlerProvider(Private);
}

getEditPath(panelId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ export function visualizeEmbeddableFactoryProvider(Private) {
const VisualizeEmbeddableFactoryProvider = (
savedVisualizations,
timefilter,
Notifier,
Promise,
Private,
config) => {
return new VisualizeEmbeddableFactory(savedVisualizations, timefilter, Notifier, Promise, Private, config);
return new VisualizeEmbeddableFactory(savedVisualizations, timefilter, Promise, Private, config);
};
return Private(VisualizeEmbeddableFactoryProvider);
}
Expand Down
Loading