Kibana app migration: Move static code dependencies into kibana_legacy plugin, part 1 (#56408) (#57095)

* Migrate PromiseServiceCreator

* Migrate migrateLegacyQuery

* Migrate watch_multi decorator

* Migrate call_after_bindings_workaround

* Migrate configureAppAngularModule, ensureDefaultIndexPattern and deps

* Migrate kbn_accessible_clicks

* Migrate PrivateProvider

* Migrate registerListenEventListener

* Adapt i18n files
This commit is contained in:
Matthias Wilhelm 2020-02-07 15:22:55 +01:00 committed by GitHub
parent 3e21bfde54
commit a21218da5b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
64 changed files with 553 additions and 491 deletions

View file

@ -27,6 +27,7 @@
"src/plugins/management"
],
"advancedSettings": "src/plugins/advanced_settings",
"kibana_legacy": "src/plugins/kibana_legacy",
"kibana_react": "src/legacy/core_plugins/kibana_react",
"kibana-react": "src/plugins/kibana_react",
"kibana_utils": "src/plugins/kibana_utils",

View file

@ -29,26 +29,26 @@ import chrome from 'ui/chrome';
export const legacyChrome = chrome;
export { SavedObjectSaveOpts } from 'ui/saved_objects/types';
export { npSetup, npStart } from 'ui/new_platform';
export { IPrivate } from 'ui/private';
export { subscribeWithScope } from 'ui/utils/subscribe_with_scope';
// @ts-ignore
export { ConfirmationButtonTypes } from 'ui/modals/confirm_modal';
export { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query';
export { KbnUrl } from 'ui/url/kbn_url';
// @ts-ignore
export { PrivateProvider } from 'ui/private/private';
// @ts-ignore
export { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav';
// @ts-ignore
export { PromiseServiceCreator } from 'ui/promises/promises';
// @ts-ignore
export { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url/index';
// @ts-ignore
export { confirmModalFactory } from 'ui/modals/confirm_modal';
export { configureAppAngularModule } from 'ui/legacy_compat';
export { ensureDefaultIndexPattern } from 'ui/legacy_compat';
export { IInjector } from 'ui/chrome';
export { SavedObjectLoader } from 'ui/saved_objects';
export { VISUALIZE_EMBEDDABLE_TYPE } from '../../../visualizations/public/embeddable';
export { registerTimefilterWithGlobalStateFactory } from 'ui/timefilter/setup_router';
export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url';
export {
configureAppAngularModule,
ensureDefaultIndexPattern,
IPrivate,
migrateLegacyQuery,
PrivateProvider,
PromiseServiceCreator,
} from '../../../../../plugins/kibana_legacy/public';

View file

@ -22,26 +22,15 @@
// They can stay even after NP cutover
import angular from 'angular';
import 'ui/angular-bootstrap';
import { IPrivate } from 'ui/private';
import { EuiIcon } from '@elastic/eui';
// @ts-ignore
import { StateProvider } from 'ui/state_management/state';
// @ts-ignore
import { EventsProvider } from 'ui/events';
import { PersistedState } from 'ui/persisted_state';
// @ts-ignore
import { PromiseServiceCreator } from 'ui/promises/promises';
import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular';
// @ts-ignore
import { PrivateProvider } from 'ui/private/private';
import { CoreStart, LegacyCoreStart, IUiSettingsClient } from 'kibana/public';
// @ts-ignore
import { watchMultiDecorator } from 'ui/directives/watch_multi/watch_multi';
// @ts-ignore
import { registerListenEventListener } from 'ui/directives/listen/listen';
// @ts-ignore
import { KbnAccessibleClickProvider } from 'ui/accessibility/kbn_accessible_click';
// @ts-ignore
import { AppStateProvider } from 'ui/state_management/app_state';
// @ts-ignore
import { GlobalStateProvider } from 'ui/state_management/global_state';
@ -51,7 +40,6 @@ import { StateManagementConfigProvider } from 'ui/state_management/config_provid
import { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url';
// @ts-ignore
import { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav';
import { configureAppAngularModule } from 'ui/legacy_compat';
import { IndexPatterns, DataPublicPluginStart } from '../../../../../plugins/data/public';
import { Storage } from '../../../../../plugins/kibana_utils/public';
import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public';
@ -82,6 +70,15 @@ import { FixedScrollProvider } from './np_ready/angular/directives/fixed_scroll'
// @ts-ignore
import { DebounceProviderTimeout } from './np_ready/angular/directives/debounce/debounce';
import { createRenderCompleteDirective } from './np_ready/angular/directives/render_complete';
import {
configureAppAngularModule,
IPrivate,
KbnAccessibleClickProvider,
PrivateProvider,
PromiseServiceCreator,
registerListenEventListener,
watchMultiDecorator,
} from '../../../../../plugins/kibana_legacy/public';
/**
* returns the main inner angular module, it contains all the parts of Angular Discover

View file

@ -51,23 +51,22 @@ export function setServices(newServices: any) {
export { angular };
export { wrapInI18nContext } from 'ui/i18n';
export { buildVislibDimensions } from '../../../visualizations/public';
// @ts-ignore
export { callAfterBindingsWorkaround } from 'ui/compat';
export { getRequestInspectorStats, getResponseInspectorStats } from '../../../data/public';
// @ts-ignore
export { intervalOptions } from 'ui/agg_types';
// @ts-ignore
export { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query';
export { stateMonitorFactory } from 'ui/state_management/state_monitor_factory';
export { subscribeWithScope } from 'ui/utils/subscribe_with_scope';
// @ts-ignore
export { timezoneProvider } from 'ui/vis/lib/timezone';
// @ts-ignore
export { tabifyAggResponse } from 'ui/agg_response/tabify';
export { ensureDefaultIndexPattern } from 'ui/legacy_compat';
export { unhashUrl } from '../../../../../plugins/kibana_utils/public';
// @ts-ignore
export { formatMsg, formatStack } from 'ui/notify/lib/index';
export {
migrateLegacyQuery,
ensureDefaultIndexPattern,
formatMsg,
formatStack,
} from '../../../../../plugins/kibana_legacy/public';
// EXPORT types
export {

View file

@ -49,26 +49,6 @@
*
*/
export class InitAfterBindingsWorkaround {
static $inject = ['$injector', '$attrs', '$element', '$scope', '$transclude'];
constructor($injector, $attrs, $element, $scope, $transclude) {
if (!this.initAfterBindings) {
throw new Error(
'When using inheritance you must move the logic in the constructor to the `initAfterBindings` method'
);
}
this.$onInit = () => {
$injector.invoke(this.initAfterBindings, this, {
$attrs,
$element,
$scope,
$transclude,
});
};
}
}
export function callAfterBindingsWorkaround(constructor) {
return function InitAfterBindingsWrapper($injector, $attrs, $element, $scope, $transclude) {
this.$onInit = () => {

View file

@ -18,7 +18,7 @@
*/
import _ from 'lodash';
import { callAfterBindingsWorkaround, getAngularModule } from '../../kibana_services';
import { getAngularModule } from '../../kibana_services';
import contextAppTemplate from './context_app.html';
import './context/components/action_bar';
import { getFirstSortableField } from './context/api/utils/sorting';
@ -33,6 +33,7 @@ import {
LOADING_STATUS,
QueryActionsProvider,
} from './context/query';
import { callAfterBindingsWorkaround } from './context/helpers/call_after_bindings_workaround';
const module = getAngularModule();

View file

@ -21,12 +21,12 @@ import { EuiCallOut, EuiCodeBlock } from '@elastic/eui';
import { formatMsg, formatStack } from '../../../kibana_services';
interface Props {
error: Error | string | null;
error: Error | string;
}
export function DocViewerError({ error }: Props) {
const errMsg = formatMsg(error);
const errStack = error ? formatStack(error) : '';
const errStack = typeof error === 'object' ? formatStack(error) : '';
return (
<EuiCallOut title={errMsg} color="danger" iconType="cross" data-test-subj="docViewerError">

View file

@ -31,7 +31,7 @@ interface Props {
}
interface State {
error: null | Error | string;
error: Error | string;
hasError: boolean;
}
/**
@ -42,7 +42,7 @@ interface State {
export class DocViewerTab extends React.Component<Props, State> {
state = {
hasError: false,
error: null,
error: '',
};
static getDerivedStateFromError(error: unknown) {

View file

@ -20,9 +20,9 @@
import { FeatureCatalogueRegistryProvider } from 'ui/registry/feature_catalogue';
import { npSetup, npStart } from 'ui/new_platform';
import chrome from 'ui/chrome';
import { IPrivate } from 'ui/private';
import { HomePlugin, LegacyAngularInjectedDependencies } from './plugin';
import { TelemetryOptInProvider } from '../../../telemetry/public/services';
import { IPrivate } from '../../../../../plugins/kibana_legacy/public';
/**
* Get dependencies relying on the global angular context.

View file

@ -40,31 +40,29 @@ export { stateMonitorFactory } from 'ui/state_management/state_monitor_factory';
export { PersistedState } from 'ui/persisted_state';
export { npSetup, npStart } from 'ui/new_platform';
export { IPrivate } from 'ui/private';
// @ts-ignore
export { PrivateProvider } from 'ui/private/private';
export { subscribeWithScope } from 'ui/utils/subscribe_with_scope';
export { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query';
// @ts-ignore
export { EventsProvider } from 'ui/events';
// @ts-ignore
export { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav';
// @ts-ignore
export { PromiseServiceCreator } from 'ui/promises/promises';
// @ts-ignore
export { confirmModalFactory } from 'ui/modals/confirm_modal';
export { configureAppAngularModule, ensureDefaultIndexPattern } from 'ui/legacy_compat';
export { registerTimefilterWithGlobalStateFactory } from 'ui/timefilter/setup_router';
// @ts-ignore
export { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url';
export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url';
export { KibanaParsedUrl } from 'ui/url/kibana_parsed_url';
export { wrapInI18nContext } from 'ui/i18n';
export { DashboardConstants } from '../dashboard/np_ready/dashboard_constants';
export { VisSavedObject } from '../../../visualizations/public/embeddable/visualize_embeddable';
export { VISUALIZE_EMBEDDABLE_TYPE } from '../../../visualizations/public/embeddable';
export { VisType } from '../../../visualizations/public';
export {
configureAppAngularModule,
ensureDefaultIndexPattern,
IPrivate,
migrateLegacyQuery,
PrivateProvider,
PromiseServiceCreator,
} from '../../../../../plugins/kibana_legacy/public';

View file

@ -20,22 +20,18 @@
export { npSetup, npStart } from 'ui/new_platform';
export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities';
export { IAggConfig, AggGroupNames, Schemas } from 'ui/agg_types';
// @ts-ignore
export { PrivateProvider } from 'ui/private/private';
// @ts-ignore
export { PaginateDirectiveProvider } from 'ui/directives/paginate';
// @ts-ignore
export { PaginateControlsDirectiveProvider } from 'ui/directives/paginate';
// @ts-ignore
export { watchMultiDecorator } from 'ui/directives/watch_multi/watch_multi';
// @ts-ignore
export { KbnAccessibleClickProvider } from 'ui/accessibility/kbn_accessible_click';
// @ts-ignore
export { StateManagementConfigProvider } from 'ui/state_management/config_provider';
export { configureAppAngularModule } from 'ui/legacy_compat';
export { tabifyGetColumns } from 'ui/agg_response/tabify/_get_columns';
// @ts-ignore
export { tabifyAggResponse } from 'ui/agg_response/tabify';
export {
configureAppAngularModule,
KbnAccessibleClickProvider,
PrivateProvider,
watchMultiDecorator,
} from '../../../../plugins/kibana_legacy/public';

View file

@ -5,4 +5,4 @@ In this directory you'll find various UI systems you can use to craft effective
## ui/notify
* [banners](notify/banners/BANNERS.md)
* [toastNotifications](notify/toasts/TOAST_NOTIFICATIONS.md)
* [toastNotifications](../../../plugins/kibana_legacy/public/notify/toasts/TOAST_NOTIFICATIONS.md)

View file

@ -37,58 +37,7 @@
* Apply this directive to any of these elements to automatically do the above.
*/
import { accessibleClickKeys, keyCodes } from '@elastic/eui';
import { uiModules } from '../modules';
export function KbnAccessibleClickProvider() {
return {
restrict: 'A',
controller: $element => {
$element.on('keydown', e => {
// Prevent a scroll from occurring if the user has hit space.
if (e.keyCode === keyCodes.SPACE) {
e.preventDefault();
}
});
},
link: (scope, element, attrs) => {
// The whole point of this directive is to hack in functionality that native buttons provide
// by default.
const elementType = element.prop('tagName');
if (elementType === 'BUTTON') {
throw new Error(`kbnAccessibleClick doesn't need to be used on a button.`);
}
if (elementType === 'A' && attrs.href !== undefined) {
throw new Error(
`kbnAccessibleClick doesn't need to be used on a link if it has a href attribute.`
);
}
// We're emulating a click action, so we should already have a regular click handler defined.
if (!attrs.ngClick) {
throw new Error('kbnAccessibleClick requires ng-click to be defined on its element.');
}
// If the developer hasn't already specified attributes required for accessibility, add them.
if (attrs.tabindex === undefined) {
element.attr('tabindex', '0');
}
if (attrs.role === undefined) {
element.attr('role', 'button');
}
element.on('keyup', e => {
// Support keyboard accessibility by emulating mouse click on ENTER or SPACE keypress.
if (accessibleClickKeys[e.keyCode]) {
// Delegate to the click handler on the element (assumed to be ng-click).
element.click();
}
});
},
};
}
import { KbnAccessibleClickProvider } from '../../../../plugins/kibana_legacy/public';
uiModules.get('kibana').directive('kbnAccessibleClick', KbnAccessibleClickProvider);

View file

@ -18,23 +18,6 @@
*/
import { uiModules } from '../../modules';
export function registerListenEventListener($rootScope) {
/**
* Helper that registers an event listener, and removes that listener when
* the $scope is destroyed.
*
* @param {SimpleEmitter} emitter - the event emitter to listen to
* @param {string} eventName - the event name
* @param {Function} handler - the event handler
* @return {undefined}
*/
$rootScope.constructor.prototype.$listen = function(emitter, eventName, handler) {
emitter.on(eventName, handler);
this.$on('$destroy', function() {
emitter.off(eventName, handler);
});
};
}
import { registerListenEventListener } from '../../../../../plugins/kibana_legacy/public';
uiModules.get('kibana').run(registerListenEventListener);

View file

@ -17,4 +17,6 @@
* under the License.
*/
import './watch_multi';
import { uiModules } from '../../modules';
import { watchMultiDecorator } from '../../../../../plugins/kibana_legacy/public';
uiModules.get('kibana').config(watchMultiDecorator);

View file

@ -18,7 +18,7 @@
*/
import expect from '@kbn/expect';
import { IE_REGEX } from '../url_overflow_service.js';
import { IE_REGEX } from '../../../../../plugins/kibana_legacy/public';
describe('IE_REGEX', () => {
it('should detect IE 9', () => {

View file

@ -22,9 +22,9 @@ import uiRoutes from '../routes';
import { KbnUrlProvider } from '../url';
import template from './error_url_overflow.html';
import { UrlOverflowService } from './url_overflow_service';
import { UrlOverflowService } from '../../../../plugins/kibana_legacy/public';
export * from './url_overflow_service';
export { UrlOverflowService };
uiRoutes.when('/error/url-overflow', {
template,

View file

@ -18,4 +18,4 @@
*/
import './error_url_overflow';
export { UrlOverflowService } from './url_overflow_service';
export { UrlOverflowService } from '../../../../plugins/kibana_legacy/public';

View file

@ -22,7 +22,7 @@ import expect from '@kbn/expect';
import sinon from 'sinon';
import ngMock from 'ng_mock';
import { $setupXsrfRequestInterceptor } from '../angular_config';
import { $setupXsrfRequestInterceptor } from '../../../../../plugins/kibana_legacy/public';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { version } from '../../../../../core/server/utils/package_json';

View file

@ -17,5 +17,7 @@
* under the License.
*/
export { configureAppAngularModule } from './angular_config';
export { ensureDefaultIndexPattern } from './ensure_default_index_pattern';
export {
configureAppAngularModule,
ensureDefaultIndexPattern,
} from '../../../../plugins/kibana_legacy/public';

View file

@ -22,7 +22,7 @@ import {
AngularHttpError,
formatAngularHttpError,
isAngularHttpError,
} from './lib/format_angular_http_error';
} from '../../../../plugins/kibana_legacy/public';
export function addFatalErrorCallback(callback: () => void) {
npSetup.core.fatalErrors.get$().subscribe(() => {

View file

@ -17,5 +17,5 @@
* under the License.
*/
export { toastNotifications, Toast, ToastInput } from './toasts';
export { toastNotifications } from './toasts';
export { fatalError } from './fatal_error';

View file

@ -19,5 +19,5 @@
export { fatalError, addFatalErrorCallback } from './fatal_error';
export { toastNotifications } from './toasts';
export { banners } from './banners';
export { addAppRedirectMessageToUrl, showAppRedirectNotification } from './app_redirect';
export { banners } from './banners';

View file

@ -16,6 +16,5 @@
* specific language governing permissions and limitations
* under the License.
*/
export { ToastNotifications } from './toast_notifications';
export { toastNotifications } from './toasts';
export { Toast, ToastInput } from './toast_notifications';

View file

@ -16,40 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import {
ErrorToastOptions,
NotificationsSetup,
Toast,
ToastInput,
} from '../../../../../core/public';
export { Toast, ToastInput };
export class ToastNotifications {
public list: Toast[] = [];
private onChangeCallback?: () => void;
constructor(private readonly toasts: NotificationsSetup['toasts']) {
toasts.get$().subscribe(list => {
this.list = list;
if (this.onChangeCallback) {
this.onChangeCallback();
}
});
}
public onChange = (callback: () => void) => {
this.onChangeCallback = callback;
};
public add = (toastOrTitle: ToastInput) => this.toasts.add(toastOrTitle);
public remove = (toast: Toast) => this.toasts.remove(toast);
public addSuccess = (toastOrTitle: ToastInput) => this.toasts.addSuccess(toastOrTitle);
public addWarning = (toastOrTitle: ToastInput) => this.toasts.addWarning(toastOrTitle);
public addDanger = (toastOrTitle: ToastInput) => this.toasts.addDanger(toastOrTitle);
public addError = (error: Error, options: ErrorToastOptions) =>
this.toasts.addError(error, options);
}
/**
* ToastNotifications is deprecated! Please use npSetup.core.notifications.toasts instead
*/
export { ToastNotifications } from '../../../../../plugins/kibana_legacy/public';

View file

@ -19,5 +19,4 @@
import { npSetup } from 'ui/new_platform';
import { ToastNotifications } from './toast_notifications';
export const toastNotifications = new ToastNotifications(npSetup.core.notifications.toasts);

View file

@ -17,4 +17,4 @@
* under the License.
*/
export { IPrivate } from './private';
export { IPrivate } from '../../../../plugins/kibana_legacy/public/utils/private';

View file

@ -17,196 +17,7 @@
* under the License.
*/
import _ from 'lodash';
import { uiModules } from '../modules';
/**
* # `Private()`
* Private module loader, used to merge angular and require js dependency styles
* by allowing a require.js module to export a single provider function that will
* create a value used within an angular application. This provider can declare
* angular dependencies by listing them as arguments, and can be require additional
* Private modules.
*
* ## Define a private module provider:
* ```js
* export default function PingProvider($http) {
* this.ping = function () {
* return $http.head('/health-check');
* };
* };
* ```
*
* ## Require a private module:
* ```js
* export default function ServerHealthProvider(Private, Promise) {
* let ping = Private(require('ui/ping'));
* return {
* check: Promise.method(function () {
* let attempts = 0;
* return (function attempt() {
* attempts += 1;
* return ping.ping()
* .catch(function (err) {
* if (attempts < 3) return attempt();
* })
* }())
* .then(function () {
* return true;
* })
* .catch(function () {
* return false;
* });
* })
* }
* };
* ```
*
* # `Private.stub(provider, newInstance)`
* `Private.stub()` replaces the instance of a module with another value. This is all we have needed until now.
*
* ```js
* beforeEach(inject(function ($injector, Private) {
* Private.stub(
* // since this module just exports a function, we need to change
* // what Private returns in order to modify it's behavior
* require('ui/agg_response/hierarchical/_build_split'),
* sinon.stub().returns(fakeSplit)
* );
* }));
* ```
*
* # `Private.swap(oldProvider, newProvider)`
* This new method does an 1-for-1 swap of module providers, unlike `stub()` which replaces a modules instance.
* Pass the module you want to swap out, and the one it should be replaced with, then profit.
*
* Note: even though this example shows `swap()` being called in a config
* function, it can be called from anywhere. It is particularly useful
* in this scenario though.
*
* ```js
* beforeEach(module('kibana', function (PrivateProvider) {
* PrivateProvider.swap(
* function StubbedRedirectProvider($decorate) {
* // $decorate is a function that will instantiate the original module when called
* return sinon.spy($decorate());
* }
* );
* }));
* ```
*
* @param {[type]} prov [description]
*/
const nextId = _.partial(_.uniqueId, 'privateProvider#');
function name(fn) {
return (
fn.name ||
fn
.toString()
.split('\n')
.shift()
);
}
export function PrivateProvider() {
const provider = this;
// one cache/swaps per Provider
const cache = {};
const swaps = {};
// return the uniq id for this function
function identify(fn) {
if (typeof fn !== 'function') {
throw new TypeError('Expected private module "' + fn + '" to be a function');
}
if (fn.$$id) return fn.$$id;
else return (fn.$$id = nextId());
}
provider.stub = function(fn, instance) {
cache[identify(fn)] = instance;
return instance;
};
provider.swap = function(fn, prov) {
const id = identify(fn);
swaps[id] = prov;
};
provider.$get = [
'$injector',
function PrivateFactory($injector) {
// prevent circular deps by tracking where we came from
const privPath = [];
const pathToString = function() {
return privPath.map(name).join(' -> ');
};
// call a private provider and return the instance it creates
function instantiate(prov, locals) {
if (~privPath.indexOf(prov)) {
throw new Error(
'Circular reference to "' +
name(prov) +
'"' +
' found while resolving private deps: ' +
pathToString()
);
}
privPath.push(prov);
const context = {};
let instance = $injector.invoke(prov, context, locals);
if (!_.isObject(instance)) instance = context;
privPath.pop();
return instance;
}
// retrieve an instance from cache or create and store on
function get(id, prov, $delegateId, $delegateProv) {
if (cache[id]) return cache[id];
let instance;
if ($delegateId != null && $delegateProv != null) {
instance = instantiate(prov, {
$decorate: _.partial(get, $delegateId, $delegateProv),
});
} else {
instance = instantiate(prov);
}
return (cache[id] = instance);
}
// main api, get the appropriate instance for a provider
function Private(prov) {
let id = identify(prov);
let $delegateId;
let $delegateProv;
if (swaps[id]) {
$delegateId = id;
$delegateProv = prov;
prov = swaps[$delegateId];
id = identify(prov);
}
return get(id, prov, $delegateId, $delegateProv);
}
Private.stub = provider.stub;
Private.swap = provider.swap;
return Private;
},
];
}
import { PrivateProvider } from '../../../../plugins/kibana_legacy/public';
uiModules.get('kibana/private').provider('Private', PrivateProvider);

View file

@ -17,9 +17,12 @@
* under the License.
*/
export interface PromiseService {
resolve: <T>(value: T | PromiseLike<T>) => ng.IPromise<T>;
import { PromiseServiceCreator } from '../../../../plugins/kibana_legacy/public';
export { createDefer } from './defer';
// @ts-ignore
import { uiModules } from '../modules';
// TODO: add additional typing
[key: string]: any;
}
const module = uiModules.get('kibana');
// Provides a tiny subset of the excellent API from
// bluebird, reimplemented using the $q service
module.service('Promise', PromiseServiceCreator);

View file

@ -17,7 +17,7 @@
* under the License.
*/
import _ from 'lodash';
import { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query';
import { migrateLegacyQuery } from '../../../../../plugins/kibana_legacy/public';
import { SavedObject } from '../types';
import { InvalidJSONProperty } from '../../../../../plugins/kibana_utils/public';

View file

@ -18,7 +18,10 @@
*/
import expect from '@kbn/expect';
import { addSystemApiHeader, isSystemApiRequest } from '../system_api';
import {
addSystemApiHeader,
isSystemApiRequest,
} from '../../../../../plugins/kibana_legacy/public';
describe('system_api', () => {
describe('#addSystemApiHeader', () => {

View file

@ -17,4 +17,4 @@
* under the License.
*/
export { addSystemApiHeader, isSystemApiRequest } from './system_api';
export { addSystemApiHeader, isSystemApiRequest } from '../../../../plugins/kibana_legacy/public';

View file

@ -28,26 +28,34 @@ import {
IRootScopeService,
} from 'angular';
import $ from 'jquery';
import _, { cloneDeep, forOwn, get, set } from 'lodash';
import { cloneDeep, forOwn, get, set } from 'lodash';
import React, { Fragment } from 'react';
import * as Rx from 'rxjs';
import { ChromeBreadcrumb } from 'kibana/public';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { CoreStart, LegacyCoreStart } from 'kibana/public';
import { fatalError } from 'ui/notify';
import { RouteConfiguration } from 'ui/routes/route_manager';
// @ts-ignore
import { modifyUrl } from 'ui/url';
import { toMountPoint } from '../../../../plugins/kibana_react/public';
// @ts-ignore
import { UrlOverflowService } from '../error_url_overflow';
// @ts-ignore
import { isSystemApiRequest } from '../system_api';
import { modifyUrl } from '../../../../core/utils';
import { toMountPoint } from '../../../kibana_react/public';
import { isSystemApiRequest, UrlOverflowService } from '../utils';
import { formatAngularHttpError, isAngularHttpError } from '../notify/lib';
const URL_LIMIT_WARN_WITHIN = 1000;
export interface RouteConfiguration {
controller?: string | ((...args: any[]) => void);
redirectTo?: string;
resolveRedirectTo?: (...args: any[]) => void;
reloadOnSearch?: boolean;
reloadOnUrl?: boolean;
outerAngularWrapperRoute?: boolean;
resolve?: object;
template?: string;
k7Breadcrumbs?: (...args: any[]) => ChromeBreadcrumb[];
requireUICapability?: string;
}
/**
* Detects whether a given angular route is a dummy route that doesn't
* require any action. There are two ways this can happen:
@ -91,7 +99,7 @@ export const configureAppAngularModule = (
.value('esUrl', getEsUrl(newPlatform))
.value('uiCapabilities', newPlatform.application.capabilities)
.config(setupCompileProvider(newPlatform))
.config(setupLocationProvider(newPlatform))
.config(setupLocationProvider())
.config($setupXsrfRequestInterceptor(newPlatform))
.run(capture$httpLoadingCount(newPlatform))
.run($setupBreadcrumbsAutoClear(newPlatform, isLocalAngular))
@ -122,9 +130,7 @@ const setupCompileProvider = (newPlatform: LegacyCoreStart) => (
}
};
const setupLocationProvider = (newPlatform: CoreStart) => (
$locationProvider: ILocationProvider
) => {
const setupLocationProvider = () => ($locationProvider: ILocationProvider) => {
$locationProvider.html5Mode({
enabled: false,
requireBase: false,
@ -165,9 +171,6 @@ export const $setupXsrfRequestInterceptor = (newPlatform: LegacyCoreStart) => {
* and adds a root-level watcher that will capture the count of
* active $http requests on each digest loop and expose the count to
* the core.loadingCount api
* @param {Angular.Scope} $rootScope
* @param {HttpService} $http
* @return {undefined}
*/
const capture$httpLoadingCount = (newPlatform: CoreStart) => (
$rootScope: IRootScopeService,
@ -260,7 +263,10 @@ const $setupBreadcrumbsAutoClear = (newPlatform: CoreStart, isLocalAngular: bool
try {
newPlatform.chrome.setBreadcrumbs($injector.invoke(k7BreadcrumbsProvider));
} catch (error) {
fatalError(error);
if (isAngularHttpError(error)) {
error = formatAngularHttpError(error);
}
newPlatform.fatalErrors.add(error, 'location');
}
});
};
@ -302,7 +308,10 @@ const $setupBadgeAutoClear = (newPlatform: CoreStart, isLocalAngular: boolean) =
try {
newPlatform.chrome.setBadge($injector.invoke(badgeProvider));
} catch (error) {
fatalError(error);
if (isAngularHttpError(error)) {
error = formatAngularHttpError(error);
}
newPlatform.fatalErrors.add(error, 'location');
}
});
};
@ -374,13 +383,13 @@ const $setupUrlOverflowHandling = (newPlatform: CoreStart, isLocalAngular: boole
try {
if (urlOverflow.check($location.absUrl()) <= URL_LIMIT_WARN_WITHIN) {
newPlatform.notifications.toasts.addWarning({
title: i18n.translate('common.ui.chrome.bigUrlWarningNotificationTitle', {
title: i18n.translate('kibana_legacy.bigUrlWarningNotificationTitle', {
defaultMessage: 'The URL is big and Kibana might stop working',
}),
text: toMountPoint(
<Fragment>
<FormattedMessage
id="common.ui.chrome.bigUrlWarningNotificationMessage"
id="kibana_legacy.bigUrlWarningNotificationMessage"
defaultMessage="Either enable the {storeInSessionStorageParam} option
in {advancedSettingsLink} or simplify the onscreen visuals."
values={{
@ -388,7 +397,7 @@ const $setupUrlOverflowHandling = (newPlatform: CoreStart, isLocalAngular: boole
advancedSettingsLink: (
<a href="#/management/kibana/settings">
<FormattedMessage
id="common.ui.chrome.bigUrlWarningNotificationMessage.advancedSettingsLinkText"
id="kibana_legacy.bigUrlWarningNotificationMessage.advancedSettingsLinkText"
defaultMessage="advanced settings"
/>
</a>

View file

@ -79,7 +79,7 @@ export async function ensureDefaultIndexPattern(
<EuiCallOut
color="warning"
iconType="iInCircle"
title={i18n.translate('common.ui.indexPattern.bannerLabel', {
title={i18n.translate('kibana_legacy.indexPattern.bannerLabel', {
defaultMessage:
"In order to visualize and explore data in Kibana, you'll need to create an index pattern to retrieve data from Elasticsearch.",
})}

View file

@ -16,8 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
export {
InitAfterBindingsWorkaround,
callAfterBindingsWorkaround,
} from './init_after_bindings_workaround';
// @ts-ignore
export { PromiseServiceCreator } from './promises';
// @ts-ignore
export { watchMultiDecorator } from './watch_multi';
export * from './angular_config';
export { ensureDefaultIndexPattern } from './ensure_default_index_pattern';

View file

@ -18,9 +18,6 @@
*/
import _ from 'lodash';
import { uiModules } from '../modules';
const module = uiModules.get('kibana');
export function PromiseServiceCreator($q, $timeout) {
function Promise(fn) {
@ -130,7 +127,3 @@ export function PromiseServiceCreator($q, $timeout) {
return Promise;
}
// Provides a tiny subset of the excellent API from
// bluebird, reimplemented using the $q service
module.service('Promise', PromiseServiceCreator);

View file

@ -18,7 +18,6 @@
*/
import _ from 'lodash';
import { uiModules } from '../../modules';
export function watchMultiDecorator($provide) {
$provide.decorator('$rootScope', function($delegate) {
@ -147,5 +146,3 @@ export function watchMultiDecorator($provide) {
return $delegate;
});
}
uiModules.get('kibana').config(watchMultiDecorator);

View file

@ -24,3 +24,6 @@ export const plugin = (initializerContext: PluginInitializerContext) =>
new KibanaLegacyPlugin(initializerContext);
export * from './plugin';
export * from './angular';
export * from './notify';
export * from './utils';

View file

@ -16,5 +16,5 @@
* specific language governing permissions and limitations
* under the License.
*/
export { PromiseService } from './promises';
export * from './toasts';
export * from './lib';

View file

@ -36,7 +36,7 @@ export function formatAngularHttpError(error: AngularHttpError) {
// is an Angular $http "error object"
if (error.status === -1) {
// status = -1 indicates that the request was failed to reach the server
return i18n.translate('common.ui.notify.fatalError.unavailableServerErrorMessage', {
return i18n.translate('kibana_legacy.notify.fatalError.unavailableServerErrorMessage', {
defaultMessage:
'An HTTP request has failed to connect. ' +
'Please check if the Kibana server is running and that your browser has a working connection, ' +
@ -44,7 +44,7 @@ export function formatAngularHttpError(error: AngularHttpError) {
});
}
return i18n.translate('common.ui.notify.fatalError.errorStatusMessage', {
return i18n.translate('kibana_legacy.notify.fatalError.errorStatusMessage', {
defaultMessage: 'Error {errStatus} {errStatusText}: {errMessage}',
values: {
errStatus: error.status,

View file

@ -19,20 +19,19 @@
import _ from 'lodash';
const getRootCause = err => _.get(err, 'resp.error.root_cause');
const getRootCause = (err: Record<string, any> | string) => _.get(err, 'resp.error.root_cause');
/**
* Utilize the extended error information returned from elasticsearch
* @param {Error|String} err
* @returns {string}
*/
export const formatESMsg = err => {
export const formatESMsg = (err: Record<string, any> | string) => {
const rootCause = getRootCause(err);
if (!rootCause) {
if (!Array.isArray(rootCause)) {
return;
}
const result = _.pluck(rootCause, 'reason').join('\n');
return result;
return rootCause.map((cause: Record<string, any>) => cause.reason).join('\n');
};

View file

@ -29,7 +29,7 @@ const has = _.has;
* @param {String} source - Prefix for message indicating source (optional)
* @returns {string}
*/
export function formatMsg(err, source) {
export function formatMsg(err: Record<string, any> | string, source: string = '') {
let message = '';
if (source) {
message += source + ': ';
@ -47,14 +47,14 @@ export function formatMsg(err, source) {
// is an Angular $http "error object"
if (err.status === -1) {
// status = -1 indicates that the request was failed to reach the server
message += i18n.translate('common.ui.notify.toaster.unavailableServerErrorMessage', {
message += i18n.translate('kibana_legacy.notify.toaster.unavailableServerErrorMessage', {
defaultMessage:
'An HTTP request has failed to connect. ' +
'Please check if the Kibana server is running and that your browser has a working connection, ' +
'or contact your system administrator.',
});
} else {
message += i18n.translate('common.ui.notify.toaster.errorStatusMessage', {
message += i18n.translate('kibana_legacy.notify.toaster.errorStatusMessage', {
defaultMessage: 'Error {errStatus} {errStatusText}: {errMessage}',
values: {
errStatus: err.status,
@ -68,7 +68,7 @@ export function formatMsg(err, source) {
return message;
}
formatMsg.describeError = function(err) {
formatMsg.describeError = function(err: Record<string, any>) {
if (!err) return undefined;
if (err.shortMessage) return err.shortMessage;
if (err.body && err.body.message) return err.body.message;

View file

@ -20,9 +20,9 @@
import { i18n } from '@kbn/i18n';
// browsers format Error.stack differently; always include message
export function formatStack(err) {
if (err.stack && !~err.stack.indexOf(err.message)) {
return i18n.translate('common.ui.notify.toaster.errorMessage', {
export function formatStack(err: Record<string, any>) {
if (err.stack && err.stack.indexOf(err.message) === -1) {
return i18n.translate('kibana_legacy.notify.toaster.errorMessage', {
defaultMessage: `Error: {errorMessage}
{errorStack}`,
values: {

View file

@ -20,4 +20,8 @@
export { formatESMsg } from './format_es_msg';
export { formatMsg } from './format_msg';
export { formatStack } from './format_stack';
export { isAngularHttpError, formatAngularHttpError } from './format_angular_http_error';
export {
isAngularHttpError,
formatAngularHttpError,
AngularHttpError,
} from './format_angular_http_error';

View file

@ -17,5 +17,4 @@
* under the License.
*/
import './promises';
export { createDefer } from './defer';
export { ToastNotifications } from './toast_notifications';

View file

@ -19,7 +19,7 @@
import { notificationServiceMock } from '../../../../../core/public/mocks';
import { ToastNotifications } from './toast_notifications';
import { Toast } from '../../../../../core/public';
import { Toast } from 'kibana/public';
import { BehaviorSubject } from 'rxjs';
describe('ToastNotifications', () => {

View file

@ -0,0 +1,48 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { NotificationsSetup, Toast, ToastInput, ErrorToastOptions } from 'kibana/public';
export class ToastNotifications {
public list: Toast[] = [];
private onChangeCallback?: () => void;
constructor(private readonly toasts: NotificationsSetup['toasts']) {
toasts.get$().subscribe(list => {
this.list = list;
if (this.onChangeCallback) {
this.onChangeCallback();
}
});
}
public onChange = (callback: () => void) => {
this.onChangeCallback = callback;
};
public add = (toastOrTitle: ToastInput) => this.toasts.add(toastOrTitle);
public remove = (toast: Toast) => this.toasts.remove(toast);
public addSuccess = (toastOrTitle: ToastInput) => this.toasts.addSuccess(toastOrTitle);
public addWarning = (toastOrTitle: ToastInput) => this.toasts.addWarning(toastOrTitle);
public addDanger = (toastOrTitle: ToastInput) => this.toasts.addDanger(toastOrTitle);
public addError = (error: Error, options: ErrorToastOptions) =>
this.toasts.addError(error, options);
}

View file

@ -17,15 +17,12 @@
* under the License.
*/
import MarkdownIt from 'markdown-it';
import { uiModules } from 'ui/modules';
import 'angular-sanitize';
const markdownIt = new MarkdownIt({
html: false,
linkify: true,
});
uiModules.get('kibana', ['ngSanitize']).filter('markdown', function($sanitize) {
return md => (md ? $sanitize(markdownIt.render(md)) : '');
});
export * from './migrate_legacy_query';
export * from './system_api';
export * from './url_overflow_service';
// @ts-ignore
export { KbnAccessibleClickProvider } from './kbn_accessible_click';
// @ts-ignore
export { PrivateProvider, IPrivate } from './private';
// @ts-ignore
export { registerListenEventListener } from './register_listen_event_listener';

View file

@ -0,0 +1,70 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { accessibleClickKeys, keyCodes } from '@elastic/eui';
export function KbnAccessibleClickProvider() {
return {
restrict: 'A',
controller: $element => {
$element.on('keydown', e => {
// Prevent a scroll from occurring if the user has hit space.
if (e.keyCode === keyCodes.SPACE) {
e.preventDefault();
}
});
},
link: (scope, element, attrs) => {
// The whole point of this directive is to hack in functionality that native buttons provide
// by default.
const elementType = element.prop('tagName');
if (elementType === 'BUTTON') {
throw new Error(`kbnAccessibleClick doesn't need to be used on a button.`);
}
if (elementType === 'A' && attrs.href !== undefined) {
throw new Error(
`kbnAccessibleClick doesn't need to be used on a link if it has a href attribute.`
);
}
// We're emulating a click action, so we should already have a regular click handler defined.
if (!attrs.ngClick) {
throw new Error('kbnAccessibleClick requires ng-click to be defined on its element.');
}
// If the developer hasn't already specified attributes required for accessibility, add them.
if (attrs.tabindex === undefined) {
element.attr('tabindex', '0');
}
if (attrs.role === undefined) {
element.attr('role', 'button');
}
element.on('keyup', e => {
// Support keyboard accessibility by emulating mouse click on ENTER or SPACE keypress.
if (accessibleClickKeys[e.keyCode]) {
// Delegate to the click handler on the element (assumed to be ng-click).
element.click();
}
});
},
};
}

View file

@ -0,0 +1,208 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* # `Private()`
* Private module loader, used to merge angular and require js dependency styles
* by allowing a require.js module to export a single provider function that will
* create a value used within an angular application. This provider can declare
* angular dependencies by listing them as arguments, and can be require additional
* Private modules.
*
* ## Define a private module provider:
* ```js
* export default function PingProvider($http) {
* this.ping = function () {
* return $http.head('/health-check');
* };
* };
* ```
*
* ## Require a private module:
* ```js
* export default function ServerHealthProvider(Private, Promise) {
* let ping = Private(require('ui/ping'));
* return {
* check: Promise.method(function () {
* let attempts = 0;
* return (function attempt() {
* attempts += 1;
* return ping.ping()
* .catch(function (err) {
* if (attempts < 3) return attempt();
* })
* }())
* .then(function () {
* return true;
* })
* .catch(function () {
* return false;
* });
* })
* }
* };
* ```
*
* # `Private.stub(provider, newInstance)`
* `Private.stub()` replaces the instance of a module with another value. This is all we have needed until now.
*
* ```js
* beforeEach(inject(function ($injector, Private) {
* Private.stub(
* // since this module just exports a function, we need to change
* // what Private returns in order to modify it's behavior
* require('ui/agg_response/hierarchical/_build_split'),
* sinon.stub().returns(fakeSplit)
* );
* }));
* ```
*
* # `Private.swap(oldProvider, newProvider)`
* This new method does an 1-for-1 swap of module providers, unlike `stub()` which replaces a modules instance.
* Pass the module you want to swap out, and the one it should be replaced with, then profit.
*
* Note: even though this example shows `swap()` being called in a config
* function, it can be called from anywhere. It is particularly useful
* in this scenario though.
*
* ```js
* beforeEach(module('kibana', function (PrivateProvider) {
* PrivateProvider.swap(
* function StubbedRedirectProvider($decorate) {
* // $decorate is a function that will instantiate the original module when called
* return sinon.spy($decorate());
* }
* );
* }));
* ```
*
* @param {[type]} prov [description]
*/
import _ from 'lodash';
const nextId = _.partial(_.uniqueId, 'privateProvider#');
function name(fn) {
return (
fn.name ||
fn
.toString()
.split('\n')
.shift()
);
}
export function PrivateProvider() {
const provider = this;
// one cache/swaps per Provider
const cache = {};
const swaps = {};
// return the uniq id for this function
function identify(fn) {
if (typeof fn !== 'function') {
throw new TypeError('Expected private module "' + fn + '" to be a function');
}
if (fn.$$id) return fn.$$id;
else return (fn.$$id = nextId());
}
provider.stub = function(fn, instance) {
cache[identify(fn)] = instance;
return instance;
};
provider.swap = function(fn, prov) {
const id = identify(fn);
swaps[id] = prov;
};
provider.$get = [
'$injector',
function PrivateFactory($injector) {
// prevent circular deps by tracking where we came from
const privPath = [];
const pathToString = function() {
return privPath.map(name).join(' -> ');
};
// call a private provider and return the instance it creates
function instantiate(prov, locals) {
if (~privPath.indexOf(prov)) {
throw new Error(
'Circular reference to "' +
name(prov) +
'"' +
' found while resolving private deps: ' +
pathToString()
);
}
privPath.push(prov);
const context = {};
let instance = $injector.invoke(prov, context, locals);
if (!_.isObject(instance)) instance = context;
privPath.pop();
return instance;
}
// retrieve an instance from cache or create and store on
function get(id, prov, $delegateId, $delegateProv) {
if (cache[id]) return cache[id];
let instance;
if ($delegateId != null && $delegateProv != null) {
instance = instantiate(prov, {
$decorate: _.partial(get, $delegateId, $delegateProv),
});
} else {
instance = instantiate(prov);
}
return (cache[id] = instance);
}
// main api, get the appropriate instance for a provider
function Private(prov) {
let id = identify(prov);
let $delegateId;
let $delegateProv;
if (swaps[id]) {
$delegateId = id;
$delegateProv = prov;
prov = swaps[$delegateId];
id = identify(prov);
}
return get(id, prov, $delegateId, $delegateProv);
}
Private.stub = provider.stub;
Private.swap = provider.swap;
return Private;
},
];
}

View file

@ -0,0 +1,35 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
export function registerListenEventListener($rootScope) {
/**
* Helper that registers an event listener, and removes that listener when
* the $scope is destroyed.
*
* @param {SimpleEmitter} emitter - the event emitter to listen to
* @param {string} eventName - the event name
* @param {Function} handler - the event handler
* @return {undefined}
*/
$rootScope.constructor.prototype.$listen = function(emitter, eventName, handler) {
emitter.on(eventName, handler);
this.$on('$destroy', function() {
emitter.off(eventName, handler);
});
};
}

View file

@ -17,6 +17,8 @@
* under the License.
*/
import { IRequestConfig } from 'angular';
const SYSTEM_API_HEADER_NAME = 'kbn-system-api';
/**
@ -24,7 +26,7 @@ const SYSTEM_API_HEADER_NAME = 'kbn-system-api';
* @param originalHeaders Object representing set of headers
* @return Object representing set of headers, with system API header added in
*/
export function addSystemApiHeader(originalHeaders) {
export function addSystemApiHeader(originalHeaders: Record<string, string>) {
const systemApiHeaders = {
[SYSTEM_API_HEADER_NAME]: true,
};
@ -40,6 +42,7 @@ export function addSystemApiHeader(originalHeaders) {
* @param request Object Request object created by $http service
* @return true if request is a system API request; false otherwise
*/
export function isSystemApiRequest(request) {
return !!request.headers[SYSTEM_API_HEADER_NAME];
export function isSystemApiRequest(request: IRequestConfig) {
const { headers } = request;
return headers && !!headers[SYSTEM_API_HEADER_NAME];
}

View file

@ -22,6 +22,9 @@ const URL_MAX_OTHERS = 25000;
export const IE_REGEX = /(; ?MSIE |Edge\/\d|Trident\/[\d+\.]+;.*rv:*11\.\d+)/;
export class UrlOverflowService {
private readonly _ieLike: boolean;
private _val?: string | null;
private readonly _sync: () => void;
constructor() {
const key = 'error/url-overflow/url';
const store = window.sessionStorage || {
@ -37,8 +40,11 @@ export class UrlOverflowService {
this._val = store.getItem(key);
this._sync = () => {
if (this._val == null) store.removeItem(key);
else store.setItem(key, this._val);
if (typeof this._val === 'string') {
store.setItem(key, this._val);
} else {
store.removeItem(key);
}
};
}
@ -46,7 +52,7 @@ export class UrlOverflowService {
return this._ieLike ? URL_MAX_IE : URL_MAX_OTHERS;
}
set(v) {
set(v: string) {
this._val = v;
this._sync();
}
@ -55,7 +61,7 @@ export class UrlOverflowService {
return this._val;
}
check(absUrl) {
check(absUrl: string) {
if (!this.get()) {
const urlLength = absUrl.length;
const remaining = this.failLength() - urlLength;

View file

@ -12,7 +12,7 @@ import chrome, { loadingCount } from 'ui/chrome'; // eslint-disable-line import/
import { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url'; // eslint-disable-line import/order
import { Storage } from '../../../../../src/plugins/kibana_utils/public'; // eslint-disable-line import/order
// @ts-ignore Untyped Kibana Lib
import { formatMsg } from 'ui/notify/lib/format_msg'; // eslint-disable-line import/order
import { formatMsg } from '../../../../../src/plugins/kibana_legacy/public'; // eslint-disable-line import/order
// @ts-ignore Untyped Kibana Lib
import { QueryString } from 'ui/utils/query_string'; // eslint-disable-line import/order

View file

@ -8,7 +8,6 @@ import 'ui/angular-bootstrap';
import 'ace';
export { SavedObject, SavedObjectKibanaServices } from 'ui/saved_objects/types';
export { configureAppAngularModule } from 'ui/legacy_compat';
// @ts-ignore
export { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav';
// @ts-ignore
@ -16,3 +15,4 @@ export { confirmModalFactory } from 'ui/modals/confirm_modal';
// @ts-ignore
export { addAppRedirectMessageToUrl } from 'ui/notify';
export { createSavedObjectClass } from 'ui/saved_objects/saved_object';
export { configureAppAngularModule } from '../../../../../src/plugins/kibana_legacy/public';

View file

@ -8,7 +8,7 @@ import React from 'react';
import { contains } from 'lodash';
import { toastNotifications } from 'ui/notify';
// @ts-ignore
import { formatMsg } from 'ui/notify/lib';
import { formatMsg } from '../../../../../../src/plugins/kibana_legacy/public'; // eslint-disable-line import/order
import { EuiButton, EuiSpacer, EuiText } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public';

View file

@ -181,9 +181,6 @@
"data.search.aggs.paramTypes.field.invalidSavedFieldParameterErrorMessage": "保存された {fieldParameter} パラメーターが無効になりました。新しいフィールドを選択してください。",
"data.search.aggs.paramTypes.field.requiredFieldParameterErrorMessage": "{fieldParameter} は必須パラメーターです",
"data.search.aggs.string.customLabel": "カスタムラベル",
"common.ui.chrome.bigUrlWarningNotificationMessage": "{advancedSettingsLink}で{storeInSessionStorageParam}オプションを有効にするか、オンスクリーンビジュアルを簡素化してください。",
"common.ui.chrome.bigUrlWarningNotificationMessage.advancedSettingsLinkText": "高度な設定",
"common.ui.chrome.bigUrlWarningNotificationTitle": "URLが大きく、Kibanaの動作が停止する可能性があります",
"common.ui.directives.paginate.size.allDropDownOptionLabel": "すべて",
"common.ui.dualRangeControl.mustSetBothErrorMessage": "下と上の値の両方を設定する必要があります",
"common.ui.dualRangeControl.outsideOfRangeErrorMessage": "値は {min} と {max} の間でなければなりません",
@ -356,11 +353,6 @@
"common.ui.flotCharts.tueLabel": "火",
"common.ui.flotCharts.wedLabel": "水",
"common.ui.modals.cancelButtonLabel": "キャンセル",
"common.ui.notify.fatalError.errorStatusMessage": "エラー {errStatus} {errStatusText}: {errMessage}",
"common.ui.notify.fatalError.unavailableServerErrorMessage": "HTTP リクエストが接続に失敗しました。Kibana サーバーが実行されていて、ご使用のブラウザの接続が正常に動作していることを確認するか、システム管理者にお問い合わせください。",
"common.ui.notify.toaster.errorMessage": "エラー: {errorMessage}\n {errorStack}",
"common.ui.notify.toaster.errorStatusMessage": "エラー {errStatus} {errStatusText}: {errMessage}",
"common.ui.notify.toaster.unavailableServerErrorMessage": "HTTP リクエストが接続に失敗しました。Kibana サーバーが実行されていて、ご使用のブラウザの接続が正常に動作していることを確認するか、システム管理者にお問い合わせください。",
"common.ui.paginateControls.pageSizeLabel": "ページサイズ",
"common.ui.paginateControls.scrollTopButtonLabel": "最上部に移動",
"common.ui.savedObjects.confirmModal.overwriteButtonLabel": "上書き",
@ -1931,6 +1923,14 @@
"kbn.management.settings.searchBarAriaLabel": "高度な設定を検索",
"kbn.management.settings.sectionLabel": "高度な設定",
"kbn.managementTitle": "管理",
"kibana_legacy.bigUrlWarningNotificationMessage": "{advancedSettingsLink}で{storeInSessionStorageParam}オプションを有効にするか、オンスクリーンビジュアルを簡素化してください。",
"kibana_legacy.bigUrlWarningNotificationMessage.advancedSettingsLinkText": "高度な設定",
"kibana_legacy.bigUrlWarningNotificationTitle": "URLが大きく、Kibanaの動作が停止する可能性があります",
"kibana_legacy.notify.fatalError.errorStatusMessage": "错误 {errStatus} {errStatusText}{errMessage}",
"kibana_legacy.notify.fatalError.unavailableServerErrorMessage": "HTTP 请求无法连接。请检查 Kibana 服务器是否正在运行以及您的浏览器是否具有有效的连接,或请联系您的系统管理员。",
"kibana_legacy.notify.toaster.errorMessage": "错误:{errorMessage}\n {errorStack}",
"kibana_legacy.notify.toaster.errorStatusMessage": "错误 {errStatus} {errStatusText}{errMessage}",
"kibana_legacy.notify.toaster.unavailableServerErrorMessage": "HTTP 请求无法连接。请检查 Kibana 服务器是否正在运行以及您的浏览器是否具有有效的连接,或请联系您的系统管理员。",
"home.tutorials.aerospikeMetrics.artifacts.application.label": "ディスカバリ",
"home.tutorials.aerospikeMetrics.longDescription": "「aerospike」Metricbeat モジュールは、Aerospike から内部メトリックを取得します。 [詳細]({learnMoreLink})。",
"home.tutorials.aerospikeMetrics.nameTitle": "Aerospike メトリック",

View file

@ -181,9 +181,6 @@
"data.search.aggs.paramTypes.field.invalidSavedFieldParameterErrorMessage": "已保存的 {fieldParameter} 参数现在无效。请选择新字段。",
"data.search.aggs.paramTypes.field.requiredFieldParameterErrorMessage": "{fieldParameter} 是必需字段",
"data.search.aggs.string.customLabel": "定制标签",
"common.ui.chrome.bigUrlWarningNotificationMessage": "在{advancedSettingsLink}中启用“{storeInSessionStorageParam}”选项或简化屏幕视觉效果。",
"common.ui.chrome.bigUrlWarningNotificationMessage.advancedSettingsLinkText": "高级设置",
"common.ui.chrome.bigUrlWarningNotificationTitle": "URL 过长Kibana 可能无法工作",
"common.ui.directives.paginate.size.allDropDownOptionLabel": "全部",
"common.ui.dualRangeControl.mustSetBothErrorMessage": "下限值和上限值都须设置",
"common.ui.dualRangeControl.outsideOfRangeErrorMessage": "值必须是在 {min} 到 {max} 的范围内",
@ -356,11 +353,6 @@
"common.ui.flotCharts.tueLabel": "周二",
"common.ui.flotCharts.wedLabel": "周三",
"common.ui.modals.cancelButtonLabel": "取消",
"common.ui.notify.fatalError.errorStatusMessage": "错误 {errStatus} {errStatusText}{errMessage}",
"common.ui.notify.fatalError.unavailableServerErrorMessage": "HTTP 请求无法连接。请检查 Kibana 服务器是否正在运行以及您的浏览器是否具有有效的连接,或请联系您的系统管理员。",
"common.ui.notify.toaster.errorMessage": "错误:{errorMessage}\n {errorStack}",
"common.ui.notify.toaster.errorStatusMessage": "错误 {errStatus} {errStatusText}{errMessage}",
"common.ui.notify.toaster.unavailableServerErrorMessage": "HTTP 请求无法连接。请检查 Kibana 服务器是否正在运行以及您的浏览器是否具有有效的连接,或请联系您的系统管理员。",
"common.ui.paginateControls.pageSizeLabel": "页面大小",
"common.ui.paginateControls.scrollTopButtonLabel": "滚动至顶部",
"common.ui.savedObjects.confirmModal.overwriteButtonLabel": "覆盖",
@ -1931,6 +1923,14 @@
"kbn.management.settings.searchBarAriaLabel": "搜索高级设置",
"kbn.management.settings.sectionLabel": "高级设置",
"kbn.managementTitle": "管理",
"kibana_legacy.bigUrlWarningNotificationMessage": "在{advancedSettingsLink}中启用“{storeInSessionStorageParam}”选项或简化屏幕视觉效果。",
"kibana_legacy.bigUrlWarningNotificationMessage.advancedSettingsLinkText": "高级设置",
"kibana_legacy.bigUrlWarningNotificationTitle": "URL 过长Kibana 可能无法工作",
"kibana_legacy.notify.fatalError.errorStatusMessage": "错误 {errStatus} {errStatusText}{errMessage}",
"kibana_legacy.notify.fatalError.unavailableServerErrorMessage": "HTTP 请求无法连接。请检查 Kibana 服务器是否正在运行以及您的浏览器是否具有有效的连接,或请联系您的系统管理员。",
"kibana_legacy.notify.toaster.errorMessage": "错误:{errorMessage}\n {errorStack}",
"kibana_legacy.notify.toaster.errorStatusMessage": "错误 {errStatus} {errStatusText}{errMessage}",
"kibana_legacy.notify.toaster.unavailableServerErrorMessage": "HTTP 请求无法连接。请检查 Kibana 服务器是否正在运行以及您的浏览器是否具有有效的连接,或请联系您的系统管理员。",
"home.tutorials.aerospikeMetrics.artifacts.application.label": "Discover",
"home.tutorials.aerospikeMetrics.longDescription": "Metricbeat 模块 `aerospike` 从 Aerospike 提取内部指标。[了解详情]({learnMoreLink})。",
"home.tutorials.aerospikeMetrics.nameTitle": "Aerospike 指标",