From 29e984a61c7036293ab2b0ef7da40e2e262ac9fb Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 27 Feb 2020 23:10:39 +0300 Subject: [PATCH] =?UTF-8?q?[Step=202]=20ui/persisted=5Fstate=20?= =?UTF-8?q?=F0=9F=91=89=20src/plugins/visualizations=20(#58501)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Elastic Machine --- .../data/public/search/expressions/esaggs.ts | 2 +- .../kibana/public/visualize/legacy_imports.ts | 1 - .../np_ready/editor/lib/make_stateful.ts | 2 +- .../public/visualize/np_ready/types.d.ts | 3 +- .../public/components/sidebar/sidebar.tsx | 4 +- .../public/legacy_imports.ts | 1 - .../public/vis_options_props.tsx | 3 +- .../public/legacy_imports.ts | 1 - .../vis_type_timeseries/public/metrics_fn.ts | 2 +- .../visualizations/public/legacy_imports.ts | 1 - .../public/components/visualization.tsx | 3 +- .../public/components/visualization_chart.tsx | 3 +- .../public/embeddable/visualize_embeddable.ts | 2 +- .../public/np_ready/public/expressions/vis.js | 2 +- .../expressions/visualization_function.ts | 6 +- .../np_ready/public/legacy/update_status.ts | 2 +- .../public/np_ready/public/vis_impl.js | 3 +- src/legacy/ui/public/events.js | 7 +- .../ui/public/persisted_state/errors.ts | 26 -- src/legacy/ui/public/persisted_state/index.js | 20 -- .../persisted_state/persisted_state.d.ts | 29 -- .../public/persisted_state/persisted_state.js | 253 ----------------- .../__tests__/state_monitor_factory.js | 4 +- .../ui/public/state_management/app_state.js | 2 +- src/legacy/ui/public/utils/simple_emitter.js | 141 ---------- .../ui/public/utils/simple_emitter.test.js | 176 ------------ .../utils/register_listen_event_listener.js | 2 +- src/plugins/visualizations/public/index.ts | 2 + .../public/persisted_state/index.ts} | 0 .../public/persisted_state/persisted_state.ts | 254 ++++++++++++++++++ .../persisted_state_provider.test.ts | 11 +- .../public/np_imports/legacy_imports.ts | 1 - 32 files changed, 289 insertions(+), 680 deletions(-) delete mode 100644 src/legacy/ui/public/persisted_state/errors.ts delete mode 100644 src/legacy/ui/public/persisted_state/index.js delete mode 100644 src/legacy/ui/public/persisted_state/persisted_state.d.ts delete mode 100644 src/legacy/ui/public/persisted_state/persisted_state.js delete mode 100644 src/legacy/ui/public/utils/simple_emitter.js delete mode 100644 src/legacy/ui/public/utils/simple_emitter.test.js rename src/{legacy/ui/public/persisted_state/index.d.ts => plugins/visualizations/public/persisted_state/index.ts} (100%) create mode 100644 src/plugins/visualizations/public/persisted_state/persisted_state.ts rename src/{legacy/ui => plugins/visualizations}/public/persisted_state/persisted_state_provider.test.ts (96%) diff --git a/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts b/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts index 302527e4ed549f..7a5d927d0f219a 100644 --- a/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts +++ b/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts @@ -40,7 +40,7 @@ import { import { buildTabularInspectorData } from './build_tabular_inspector_data'; import { calculateObjectHash } from '../../../../visualizations/public'; import { tabifyAggResponse } from '../../../../../core_plugins/data/public'; -import { PersistedState } from '../../../../../ui/public/persisted_state'; +import { PersistedState } from '../../../../../../plugins/visualizations/public'; import { Adapters } from '../../../../../../plugins/inspector/public'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { getQueryService, getIndexPatterns } from '../../../../../../plugins/data/public/services'; diff --git a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts index d52d31c2dd79e2..b8ee7cd378750c 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts @@ -29,7 +29,6 @@ export { State } from 'ui/state_management/state'; export { GlobalStateProvider } from 'ui/state_management/global_state'; // @ts-ignore export { StateManagementConfigProvider } from 'ui/state_management/config_provider'; -export { PersistedState } from 'ui/persisted_state'; export { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; // @ts-ignore diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/make_stateful.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/make_stateful.ts index 137d4de1fe9a82..8384585108a594 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/make_stateful.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/make_stateful.ts @@ -17,7 +17,7 @@ * under the License. */ -import { PersistedState } from '../../../legacy_imports'; +import { PersistedState } from '../../../../../../../../plugins/visualizations/public'; import { ReduxLikeStateContainer } from '../../../../../../../../plugins/kibana_utils/public'; import { VisualizeAppState, VisualizeAppStateTransitions } from '../../types'; diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/types.d.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/types.d.ts index 3b6ecb45b83b34..d95939170419b7 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/types.d.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/types.d.ts @@ -19,9 +19,10 @@ import { TimeRange, Query, Filter, DataPublicPluginStart } from 'src/plugins/data/public'; import { IEmbeddableStart } from 'src/plugins/embeddable/public'; +import { PersistedState } from 'src/plugins/visualizations/public'; import { LegacyCoreStart } from 'kibana/public'; import { Vis } from 'src/legacy/core_plugins/visualizations/public'; -import { VisSavedObject, PersistedState } from '../legacy_imports'; +import { VisSavedObject } from '../legacy_imports'; export type PureVisState = ReturnType; diff --git a/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/sidebar.tsx b/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/sidebar.tsx index 8615bcdd1bfbd5..d3b843eaaec9f2 100644 --- a/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/sidebar.tsx +++ b/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/sidebar.tsx @@ -21,13 +21,13 @@ import React, { useMemo, useState, useCallback, KeyboardEventHandler, useEffect import { get, isEqual } from 'lodash'; import { i18n } from '@kbn/i18n'; import { keyCodes, EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; - import { Vis } from 'src/legacy/core_plugins/visualizations/public'; -import { PersistedState, AggGroupNames } from '../../legacy_imports'; +import { AggGroupNames } from '../../legacy_imports'; import { DefaultEditorNavBar, OptionTab } from './navbar'; import { DefaultEditorControls } from './controls'; import { setStateParamValue, useEditorReducer, useEditorFormState, discardChanges } from './state'; import { DefaultEditorAggCommonProps } from '../agg_common_props'; +import { PersistedState } from '../../../../../../plugins/visualizations/public'; interface DefaultEditorSideBarProps { isCollapsed: boolean; diff --git a/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts b/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts index 5e547eed1c9573..832f73752a99b6 100644 --- a/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts +++ b/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts @@ -48,5 +48,4 @@ export { isValidJson, isValidInterval } from 'ui/agg_types'; export { AggParamOption } from 'ui/agg_types'; export { CidrMask } from 'ui/agg_types'; -export { PersistedState } from 'ui/persisted_state'; export * from 'ui/vis/lib'; diff --git a/src/legacy/core_plugins/vis_default_editor/public/vis_options_props.tsx b/src/legacy/core_plugins/vis_default_editor/public/vis_options_props.tsx index babcb59c6582e6..18fbba1b039b53 100644 --- a/src/legacy/core_plugins/vis_default_editor/public/vis_options_props.tsx +++ b/src/legacy/core_plugins/vis_default_editor/public/vis_options_props.tsx @@ -17,7 +17,8 @@ * under the License. */ -import { IAggConfigs, PersistedState } from './legacy_imports'; +import { PersistedState } from '../../../../plugins/visualizations/public'; +import { IAggConfigs } from './legacy_imports'; import { Vis } from '../../visualizations/public'; export interface VisOptionsProps { diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/legacy_imports.ts b/src/legacy/core_plugins/vis_type_timeseries/public/legacy_imports.ts index 401acfc8df7663..a2952b2c83afdd 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/legacy_imports.ts +++ b/src/legacy/core_plugins/vis_type_timeseries/public/legacy_imports.ts @@ -17,7 +17,6 @@ * under the License. */ -export { PersistedState } from 'ui/persisted_state'; // @ts-ignore export { defaultFeedbackMessage } from 'ui/vis/default_feedback_message'; // @ts-ignore diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/metrics_fn.ts b/src/legacy/core_plugins/vis_type_timeseries/public/metrics_fn.ts index 576723bad1e434..1f9cbecc2a354b 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/public/metrics_fn.ts +++ b/src/legacy/core_plugins/vis_type_timeseries/public/metrics_fn.ts @@ -24,10 +24,10 @@ import { KibanaContext, Render, } from '../../../../plugins/expressions/public'; +import { PersistedState } from '../../../../plugins/visualizations/public'; // @ts-ignore import { metricsRequestHandler } from './request_handler'; -import { PersistedState } from './legacy_imports'; type Input = KibanaContext | null; type Output = Promise>; diff --git a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts index 385117be8ae2ea..fb7a157b53a9ac 100644 --- a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts +++ b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts @@ -17,7 +17,6 @@ * under the License. */ -export { PersistedState } from '../../../ui/public/persisted_state'; export { AggConfigs, IAggConfig, diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization.tsx b/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization.tsx index 5a9a1830ebdf33..33830c45848e43 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization.tsx +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization.tsx @@ -19,8 +19,7 @@ import { get } from 'lodash'; import React from 'react'; - -import { PersistedState } from '../../../legacy_imports'; +import { PersistedState } from '../../../../../../../plugins/visualizations/public'; import { memoizeLast } from '../legacy/memoize'; import { VisualizationChart } from './visualization_chart'; import { VisualizationNoResults } from './visualization_noresults'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_chart.tsx b/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_chart.tsx index 95fd31049d2336..7b1a18e8066a77 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_chart.tsx +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_chart.tsx @@ -20,8 +20,7 @@ import React from 'react'; import * as Rx from 'rxjs'; import { debounceTime, filter, share, switchMap } from 'rxjs/operators'; - -import { PersistedState } from '../../../legacy_imports'; +import { PersistedState } from '../../../../../../../plugins/visualizations/public'; import { Vis, VisualizationController } from '../vis'; import { getUpdateStatus } from '../legacy/update_status'; import { ResizeChecker } from '../../../../../../../plugins/kibana_utils/public'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable.ts index 2537caa01cd46d..97e2b8f88172ec 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable.ts @@ -43,10 +43,10 @@ import { IExpressionLoaderParams, ExpressionsStart, } from '../../../../../../../plugins/expressions/public'; +import { PersistedState } from '../../../../../../../plugins/visualizations/public'; import { buildPipeline } from '../legacy/build_pipeline'; import { Vis } from '../vis'; import { getExpressions, getUiActions } from '../services'; -import { PersistedState } from '../../../legacy_imports'; import { VisSavedObject } from '../types'; const getKeys = (o: T): Array => Object.keys(o) as Array; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.js b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.js index 81224b65f77866..a891140677d603 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.js +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.js @@ -29,7 +29,7 @@ import { EventEmitter } from 'events'; import _ from 'lodash'; -import { PersistedState } from '../../../legacy_imports'; +import { PersistedState } from '../../../../../../../plugins/visualizations/public'; import { getTypes } from '../services'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_function.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_function.ts index 4ac0931c5d8655..d98eda4c50ef9f 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_function.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_function.ts @@ -19,12 +19,14 @@ import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { VisResponseValue } from '../../../../../../../plugins/visualizations/public'; +import { + VisResponseValue, + PersistedState, +} from '../../../../../../../plugins/visualizations/public'; import { ExpressionFunctionDefinition, Render, } from '../../../../../../../plugins/expressions/public'; -import { PersistedState } from '../../../legacy_imports'; import { getTypes, getIndexPatterns, getFilterManager } from '../services'; interface Arguments { diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/update_status.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/update_status.ts index 6d32a6df5f1ec6..d9af5122eadec6 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/update_status.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/update_status.ts @@ -17,7 +17,7 @@ * under the License. */ -import { PersistedState } from '../../../legacy_imports'; +import { PersistedState } from '../../../../../../../plugins/visualizations/public'; import { calculateObjectHash } from './calculate_object_hash'; import { Vis } from '../vis'; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js index 6f4ab6d708184e..2f36322c67256a 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js @@ -29,7 +29,8 @@ import { EventEmitter } from 'events'; import _ from 'lodash'; -import { AggConfigs, PersistedState } from '../../legacy_imports'; +import { PersistedState } from '../../../../../../../src/plugins/visualizations/public'; +import { AggConfigs } from '../../legacy_imports'; import { updateVisualizationConfig } from './legacy/vis_update'; import { getTypes } from './services'; diff --git a/src/legacy/ui/public/events.js b/src/legacy/ui/public/events.js index f0a21a1abd012c..00c92038e7c9f1 100644 --- a/src/legacy/ui/public/events.js +++ b/src/legacy/ui/public/events.js @@ -20,19 +20,19 @@ /** * @name Events * - * @extends SimpleEmitter + * @extends EventEmitter */ import _ from 'lodash'; +import { EventEmitter } from 'events'; import { fatalError } from './notify'; -import { SimpleEmitter } from './utils/simple_emitter'; import { createLegacyClass } from './utils/legacy_class'; import { createDefer } from 'ui/promises'; const location = 'EventEmitter'; export function EventsProvider(Promise) { - createLegacyClass(Events).inherits(SimpleEmitter); + createLegacyClass(Events).inherits(EventEmitter); function Events() { Events.Super.call(this); this._listeners = {}; @@ -79,6 +79,7 @@ export function EventsProvider(Promise) { */ Events.prototype.off = function(name, handler) { if (!name && !handler) { + this._listeners = {}; return this.removeAllListeners(); } diff --git a/src/legacy/ui/public/persisted_state/errors.ts b/src/legacy/ui/public/persisted_state/errors.ts deleted file mode 100644 index 164981107298d3..00000000000000 --- a/src/legacy/ui/public/persisted_state/errors.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 { KbnError } from '../../../../plugins/kibana_utils/public'; - -export class PersistedStateError extends KbnError { - constructor() { - super('Error with the persisted state'); - } -} diff --git a/src/legacy/ui/public/persisted_state/index.js b/src/legacy/ui/public/persisted_state/index.js deleted file mode 100644 index ab5a3e7be7d283..00000000000000 --- a/src/legacy/ui/public/persisted_state/index.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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 { PersistedState } from './persisted_state'; diff --git a/src/legacy/ui/public/persisted_state/persisted_state.d.ts b/src/legacy/ui/public/persisted_state/persisted_state.d.ts deleted file mode 100644 index b5d7513172e76b..00000000000000 --- a/src/legacy/ui/public/persisted_state/persisted_state.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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. - */ - -// It's currenty hard to properly type PersistedState, since it dynamically -// inherits the class passed into the constructor. These typings are really pretty bad -// but needed in the short term to make incremental progress elsewhere. Can't even -// just use `any` since then typescript complains about using PersistedState as a -// constructor. -export class PersistedState { - constructor(value?: any, path?: any, EmitterClass?: any); - // method you want typed so far - [prop: string]: any; -} diff --git a/src/legacy/ui/public/persisted_state/persisted_state.js b/src/legacy/ui/public/persisted_state/persisted_state.js deleted file mode 100644 index 071a39ab2b4f8d..00000000000000 --- a/src/legacy/ui/public/persisted_state/persisted_state.js +++ /dev/null @@ -1,253 +0,0 @@ -/* - * 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. - */ - -/** - * @name PersistedState - * - * @extends Events - */ - -import _ from 'lodash'; -import toPath from 'lodash/internal/toPath'; -import { PersistedStateError } from './errors'; -import { SimpleEmitter } from '../utils/simple_emitter'; - -function prepSetParams(key, value, path) { - // key must be the value, set the entire state using it - if (_.isUndefined(value) && (_.isPlainObject(key) || path.length > 0)) { - // setting entire tree, swap the key and value to write to the state - value = key; - key = undefined; - } - - // ensure the value being passed in is never mutated - return { - value: _.cloneDeep(value), - key: key, - }; -} - -export class PersistedState { - /** - * - * @param value - * @param path - * @param EmitterClass {SimpleEmitter} - a SimpleEmitter class that this class will extend. Can be used to - * inherit a custom event emitter. For example, the EventEmitter is an "angular-ized" version - * for angular components which automatically triggers a digest loop for every registered - * handler. TODO: replace angularized SimpleEmitter and force angular callers to handle digest loops manually ala - * https://github.com/elastic/kibana/issues/13855 - */ - constructor(value, path, EmitterClass = SimpleEmitter) { - EmitterClass.call(this); - - this._path = this._setPath(path); - - _.forOwn(EmitterClass.prototype, (method, methodName) => { - this[methodName] = function() { - return EmitterClass.prototype[methodName].apply(this, arguments); - }; - }); - - // Some validations - if (!this._path.length && value && !_.isPlainObject(value)) { - throw new PersistedStateError('State value must be a plain object'); - } - - value = value || this._getDefault(); - - // copy passed state values and create internal trackers - this.set(value); - this._initialized = true; // used to track state changes - } - - get(key, def) { - return _.cloneDeep(this._get(key, def)); - } - - set(key, value) { - const params = prepSetParams(key, value, this._path); - const val = this._set(params.key, params.value); - this.emit('set'); - return val; - } - - setSilent(key, value) { - const params = prepSetParams(key, value, this._path); - return this._set(params.key, params.value, true); - } - - clearAllKeys() { - Object.getOwnPropertyNames(this._changedState).forEach(key => { - this.set(key, null); - }); - } - - reset(path) { - const keyPath = this._getIndex(path); - const origValue = _.get(this._defaultState, keyPath); - const currentValue = _.get(this._mergedState, keyPath); - - if (_.isUndefined(origValue)) { - this._cleanPath(path, this._mergedState); - } else { - _.set(this._mergedState, keyPath, origValue); - } - - // clean up the changedState tree - this._cleanPath(path, this._changedState); - - if (!_.isEqual(currentValue, origValue)) this.emit('change'); - } - - getChanges() { - return _.cloneDeep(this._changedState); - } - - toJSON() { - return this.get(); - } - - toString() { - return JSON.stringify(this.toJSON()); - } - - fromString(input) { - return this.set(JSON.parse(input)); - } - - _getIndex(key) { - if (_.isUndefined(key)) return this._path; - return (this._path || []).concat(toPath(key)); - } - - _getPartialIndex(key) { - const keyPath = this._getIndex(key); - return keyPath.slice(this._path.length); - } - - _cleanPath(path, stateTree) { - const partialPath = this._getPartialIndex(path); - let remove = true; - - // recursively delete value tree, when no other keys exist - while (partialPath.length > 0) { - const lastKey = partialPath.splice(partialPath.length - 1, 1)[0]; - const statePath = this._path.concat(partialPath); - const stateVal = statePath.length > 0 ? _.get(stateTree, statePath) : stateTree; - - // if stateVal isn't an object, do nothing - if (!_.isPlainObject(stateVal)) return; - - if (remove) delete stateVal[lastKey]; - if (Object.keys(stateVal).length > 0) remove = false; - } - } - - _getDefault() { - return this._hasPath() ? undefined : {}; - } - - _setPath(path) { - const isString = _.isString(path); - const isArray = Array.isArray(path); - - if (!isString && !isArray) return []; - return isString ? [this._getIndex(path)] : path; - } - - _hasPath() { - return this._path.length > 0; - } - - _get(key, def) { - // no path and no key, get the whole state - if (!this._hasPath() && _.isUndefined(key)) { - return this._mergedState; - } - - return _.get(this._mergedState, this._getIndex(key), def); - } - - _set(key, value, silent) { - const self = this; - let stateChanged = false; - const initialState = !this._initialized; - const keyPath = this._getIndex(key); - const hasKeyPath = keyPath.length > 0; - - // if this is the initial state value, save value as the default - if (initialState) { - this._changedState = {}; - if (!this._hasPath() && _.isUndefined(key)) this._defaultState = value; - else this._defaultState = _.set({}, keyPath, value); - } - - if (!initialState) { - // no path and no key, set the whole state - if (!this._hasPath() && _.isUndefined(key)) { - // compare changedState and new state, emit an event when different - stateChanged = !_.isEqual(this._changedState, value); - this._changedState = value; - this._mergedState = _.cloneDeep(value); - } else { - // check for changes at path, emit an event when different - const curVal = hasKeyPath ? this.get(keyPath) : this._mergedState; - stateChanged = !_.isEqual(curVal, value); - - // arrays are merge by index, not desired - ensure they are replaced - if (Array.isArray(_.get(this._mergedState, keyPath))) { - if (hasKeyPath) _.set(this._mergedState, keyPath, undefined); - else this._mergedState = undefined; - } - - if (hasKeyPath) { - _.set(this._changedState, keyPath, value); - } else { - this._changedState = _.isPlainObject(value) ? value : {}; - } - } - } - - // update the merged state value - const targetObj = this._mergedState || _.cloneDeep(this._defaultState); - const sourceObj = _.merge({}, this._changedState); - - // handler arguments are (targetValue, sourceValue, key, target, source) - const mergeMethod = function(targetValue, sourceValue, mergeKey) { - // if not initial state, skip default merge method (ie. return value, see note below) - if (!initialState && _.isEqual(keyPath, self._getIndex(mergeKey))) { - // use the sourceValue or fall back to targetValue - return !_.isUndefined(sourceValue) ? sourceValue : targetValue; - } - }; - - // If `mergeMethod` is provided it is invoked to produce the merged values of the - // destination and source properties. - // If `mergeMethod` returns `undefined` the default merging method is used - this._mergedState = _.merge(targetObj, sourceObj, mergeMethod); - - // sanity check; verify that there are actually changes - if (_.isEqual(this._mergedState, this._defaultState)) this._changedState = {}; - - if (!silent && stateChanged) this.emit('change', key); - - return this; - } -} diff --git a/src/legacy/ui/public/state_management/__tests__/state_monitor_factory.js b/src/legacy/ui/public/state_management/__tests__/state_monitor_factory.js index 1ba0500de7f038..601212d2da1a56 100644 --- a/src/legacy/ui/public/state_management/__tests__/state_monitor_factory.js +++ b/src/legacy/ui/public/state_management/__tests__/state_monitor_factory.js @@ -19,9 +19,9 @@ import expect from '@kbn/expect'; import sinon from 'sinon'; +import { EventEmitter } from 'events'; import { cloneDeep } from 'lodash'; import { stateMonitorFactory } from '../state_monitor_factory'; -import { SimpleEmitter } from '../../utils/simple_emitter'; describe('stateMonitorFactory', function() { const noop = () => {}; @@ -35,7 +35,7 @@ describe('stateMonitorFactory', function() { } function createMockState(state = {}) { - const mockState = new SimpleEmitter(); + const mockState = new EventEmitter(); setState(mockState, state, false); return mockState; } diff --git a/src/legacy/ui/public/state_management/app_state.js b/src/legacy/ui/public/state_management/app_state.js index 279aff62f55af1..76675b05e0fe56 100644 --- a/src/legacy/ui/public/state_management/app_state.js +++ b/src/legacy/ui/public/state_management/app_state.js @@ -29,7 +29,7 @@ import { uiModules } from '../modules'; import { StateProvider } from './state'; -import { PersistedState } from '../persisted_state'; +import { PersistedState } from '../../../../plugins/visualizations/public'; import { createLegacyClass } from '../utils/legacy_class'; const urlParam = '_a'; diff --git a/src/legacy/ui/public/utils/simple_emitter.js b/src/legacy/ui/public/utils/simple_emitter.js deleted file mode 100644 index 6bdaae2237d558..00000000000000 --- a/src/legacy/ui/public/utils/simple_emitter.js +++ /dev/null @@ -1,141 +0,0 @@ -/* - * 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 _ from 'lodash'; - -/** - * Simple event emitter class used in the vislib. Calls - * handlers synchronously and implements a chainable api - * - * @class - */ -export function SimpleEmitter() { - this._listeners = {}; -} - -/** - * Add an event handler - * - * @param {string} name - * @param {function} handler - * @return {SimpleEmitter} - this, for chaining - */ -SimpleEmitter.prototype.on = function(name, handler) { - let handlers = this._listeners[name]; - if (!handlers) handlers = this._listeners[name] = []; - - handlers.push(handler); - - return this; -}; - -/** - * Remove an event handler - * - * @param {string} name - * @param {function} [handler] - optional handler to remove, if no handler is - * passed then all are removed - * @return {SimpleEmitter} - this, for chaining - */ -SimpleEmitter.prototype.off = function(name, handler) { - if (!this._listeners[name]) { - return this; - } - - // remove a specific handler - if (handler) _.pull(this._listeners[name], handler); - // or remove all listeners - else this._listeners[name] = null; - - return this; -}; - -/** - * Remove all event listeners bound to this emitter. - * - * @return {SimpleEmitter} - this, for chaining - */ -SimpleEmitter.prototype.removeAllListeners = function() { - this._listeners = {}; - return this; -}; - -/** - * Emit an event and all arguments to all listeners for an event name - * - * @param {string} name - * @param {*} [arg...] - any number of arguments that will be applied to each handler - * @return {SimpleEmitter} - this, for chaining - */ -SimpleEmitter.prototype.emit = _.restParam(function(name, args) { - if (!this._listeners[name]) return this; - const listeners = this.listeners(name); - let i = -1; - - while (++i < listeners.length) { - listeners[i].apply(this, args); - } - - return this; -}); - -/** - * Get a list of the event names that currently have listeners - * - * @return {array[string]} - */ -SimpleEmitter.prototype.activeEvents = function() { - return _.reduce( - this._listeners, - function(active, listeners, name) { - return active.concat(_.size(listeners) ? name : []); - }, - [] - ); -}; - -/** - * Get a list of the handler functions for a specific event - * - * @param {string} name - * @return {array[function]} - */ -SimpleEmitter.prototype.listeners = function(name) { - return this._listeners[name] ? this._listeners[name].slice(0) : []; -}; - -/** - * Get the count of handlers for a specific event - * - * @param {string} [name] - optional event name to filter by - * @return {number} - */ -SimpleEmitter.prototype.listenerCount = function(name) { - if (name) { - return _.size(this._listeners[name]); - } - - return _.reduce( - this._listeners, - function(count, handlers) { - return count + _.size(handlers); - }, - 0 - ); -}; diff --git a/src/legacy/ui/public/utils/simple_emitter.test.js b/src/legacy/ui/public/utils/simple_emitter.test.js deleted file mode 100644 index 723a59ccba1c62..00000000000000 --- a/src/legacy/ui/public/utils/simple_emitter.test.js +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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 { SimpleEmitter } from './simple_emitter'; -import sinon from 'sinon'; - -describe('SimpleEmitter class', () => { - let emitter; - - beforeEach(() => { - emitter = new SimpleEmitter(); - }); - - it('constructs an event emitter', () => { - expect(emitter).toHaveProperty('on'); - expect(emitter).toHaveProperty('off'); - expect(emitter).toHaveProperty('emit'); - expect(emitter).toHaveProperty('listenerCount'); - expect(emitter).toHaveProperty('removeAllListeners'); - }); - - describe('#listenerCount', () => { - it('counts all event listeners without any arg', () => { - expect(emitter.listenerCount()).toBe(0); - emitter.on('a', () => {}); - expect(emitter.listenerCount()).toBe(1); - emitter.on('b', () => {}); - expect(emitter.listenerCount()).toBe(2); - }); - - it('limits to the event that is passed in', () => { - expect(emitter.listenerCount()).toBe(0); - emitter.on('a', () => {}); - expect(emitter.listenerCount('a')).toBe(1); - emitter.on('a', () => {}); - expect(emitter.listenerCount('a')).toBe(2); - emitter.on('b', () => {}); - expect(emitter.listenerCount('a')).toBe(2); - expect(emitter.listenerCount('b')).toBe(1); - expect(emitter.listenerCount()).toBe(3); - }); - }); - - describe('#on', () => { - it('registers a handler', () => { - const handler = sinon.stub(); - emitter.on('a', handler); - expect(emitter.listenerCount('a')).toBe(1); - - expect(handler.callCount).toBe(0); - emitter.emit('a'); - expect(handler.callCount).toBe(1); - }); - - it('allows multiple event handlers for the same event', () => { - emitter.on('a', () => {}); - emitter.on('a', () => {}); - expect(emitter.listenerCount('a')).toBe(2); - }); - - it('allows the same function to be registered multiple times', () => { - const handler = () => {}; - emitter.on('a', handler); - expect(emitter.listenerCount()).toBe(1); - emitter.on('a', handler); - expect(emitter.listenerCount()).toBe(2); - }); - }); - - describe('#off', () => { - it('removes a listener if it was registered', () => { - const handler = sinon.stub(); - expect(emitter.listenerCount()).toBe(0); - emitter.on('a', handler); - expect(emitter.listenerCount('a')).toBe(1); - emitter.off('a', handler); - expect(emitter.listenerCount('a')).toBe(0); - }); - - it('clears all listeners if no handler is passed', () => { - emitter.on('a', () => {}); - emitter.on('a', () => {}); - expect(emitter.listenerCount()).toBe(2); - emitter.off('a'); - expect(emitter.listenerCount()).toBe(0); - }); - - it('does not mind if the listener is not registered', () => { - emitter.off('a', () => {}); - }); - - it('does not mind if the event has no listeners', () => { - emitter.off('a'); - }); - }); - - describe('#emit', () => { - it('calls the handlers in the order they were defined', () => { - let i = 0; - const incr = () => ++i; - const one = sinon.spy(incr); - const two = sinon.spy(incr); - const three = sinon.spy(incr); - const four = sinon.spy(incr); - - emitter - .on('a', one) - .on('a', two) - .on('a', three) - .on('a', four) - .emit('a'); - - expect(one).toHaveProperty('callCount', 1); - expect(one.returned(1)).toBeDefined(); - - expect(two).toHaveProperty('callCount', 1); - expect(two.returned(2)).toBeDefined(); - - expect(three).toHaveProperty('callCount', 1); - expect(three.returned(3)).toBeDefined(); - - expect(four).toHaveProperty('callCount', 1); - expect(four.returned(4)).toBeDefined(); - }); - - it('always emits the handlers that were initially registered', () => { - const destructive = sinon.spy(() => { - emitter.removeAllListeners(); - expect(emitter.listenerCount()).toBe(0); - }); - const stub = sinon.stub(); - - emitter - .on('run', destructive) - .on('run', stub) - .emit('run'); - - expect(destructive).toHaveProperty('callCount', 1); - expect(stub).toHaveProperty('callCount', 1); - }); - - it('applies all arguments except the first', () => { - emitter - .on('a', (a, b, c) => { - expect(a).toBe('foo'); - expect(b).toBe('bar'); - expect(c).toBe('baz'); - }) - .emit('a', 'foo', 'bar', 'baz'); - }); - - it('uses the SimpleEmitter as the this context', () => { - emitter - .on('a', function() { - expect(this).toBe(emitter); - }) - .emit('a'); - }); - }); -}); diff --git a/src/plugins/kibana_legacy/public/utils/register_listen_event_listener.js b/src/plugins/kibana_legacy/public/utils/register_listen_event_listener.js index cce6c98adbbfec..6cc9a5766d3fe2 100644 --- a/src/plugins/kibana_legacy/public/utils/register_listen_event_listener.js +++ b/src/plugins/kibana_legacy/public/utils/register_listen_event_listener.js @@ -21,7 +21,7 @@ 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 {EventEmitter} emitter - the event emitter to listen to * @param {string} eventName - the event name * @param {Function} handler - the event handler * @return {undefined} diff --git a/src/plugins/visualizations/public/index.ts b/src/plugins/visualizations/public/index.ts index 2b4b10c8329a3a..c08dbf890b8da9 100644 --- a/src/plugins/visualizations/public/index.ts +++ b/src/plugins/visualizations/public/index.ts @@ -27,3 +27,5 @@ export function plugin(initializerContext: PluginInitializerContext) { export { VisualizationsPublicPlugin as Plugin }; export * from './plugin'; export * from './types'; + +export { PersistedState } from './persisted_state'; diff --git a/src/legacy/ui/public/persisted_state/index.d.ts b/src/plugins/visualizations/public/persisted_state/index.ts similarity index 100% rename from src/legacy/ui/public/persisted_state/index.d.ts rename to src/plugins/visualizations/public/persisted_state/index.ts diff --git a/src/plugins/visualizations/public/persisted_state/persisted_state.ts b/src/plugins/visualizations/public/persisted_state/persisted_state.ts new file mode 100644 index 00000000000000..d09dcd5381511e --- /dev/null +++ b/src/plugins/visualizations/public/persisted_state/persisted_state.ts @@ -0,0 +1,254 @@ +/* + * 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 { EventEmitter } from 'events'; + +import { isPlainObject, cloneDeep, get, set, isEqual, isString, merge } from 'lodash'; +import toPath from 'lodash/internal/toPath'; + +function prepSetParams(key: PersistedStateKey, value: any, path: PersistedStatePath) { + // key must be the value, set the entire state using it + if (value === undefined && (isPlainObject(key) || path.length > 0)) { + // setting entire tree, swap the key and value to write to the state + return { + value: key, + key: undefined, + }; + } + + // ensure the value being passed in is never mutated + return { + value: cloneDeep(value), + key, + }; +} + +type PersistedStateKey = string | string[] | undefined; +type PersistedStatePath = string | string[]; + +export class PersistedState extends EventEmitter { + private readonly _path: PersistedStatePath; + private readonly _initialized: boolean; + + private _changedState: any; + private _defaultState: any; + private _mergedState: any; + + constructor(value?: any, path?: PersistedStatePath) { + super(); + + this._path = this.setPath(path); + + // Some validations + if (!this._path.length && value && !isPlainObject(value)) { + throw new Error('State value must be a plain object'); + } + + value = value || this.getDefault(); + + // copy passed state values and create internal trackers + this.set(value); + this._initialized = true; // used to track state changes + } + + get(key?: PersistedStateKey, defaultValue?: any) { + // no path and no key, get the whole state + if (!this.hasPath() && key === undefined) { + return this._mergedState; + } + + return cloneDeep(get(this._mergedState, this.getIndex(key || ''), defaultValue)); + } + + set(key: PersistedStateKey | any, value?: any) { + const params = prepSetParams(key, value, this._path); + const val = this.setValue(params.key, params.value); + + this.emit('set'); + return val; + } + + setSilent(key: PersistedStateKey | any, value?: any) { + const params = prepSetParams(key, value, this._path); + + if (params.key) { + return this.setValue(params.key, params.value, true); + } + } + + clearAllKeys() { + Object.getOwnPropertyNames(this._changedState).forEach(key => { + this.set(key, null); + }); + } + + reset(path: PersistedStatePath) { + const keyPath = this.getIndex(path); + const origValue = get(this._defaultState, keyPath); + const currentValue = get(this._mergedState, keyPath); + + if (origValue === undefined) { + this.cleanPath(path, this._mergedState); + } else { + set(this._mergedState, keyPath, origValue); + } + + // clean up the changedState tree + this.cleanPath(path, this._changedState); + + if (!isEqual(currentValue, origValue)) this.emit('change'); + } + + getChanges() { + return cloneDeep(this._changedState); + } + + toJSON() { + return this.get(); + } + + toString() { + return JSON.stringify(this.toJSON()); + } + + fromString(input: string) { + return this.set(JSON.parse(input)); + } + + private getIndex(key: PersistedStateKey) { + if (key === undefined) return this._path; + + return [...(this._path || []), ...toPath(key)]; + } + + private getPartialIndex(key: PersistedStateKey) { + const keyPath = this.getIndex(key); + + return keyPath.slice(this._path.length); + } + + private cleanPath(path: PersistedStatePath, stateTree: any) { + const partialPath = this.getPartialIndex(path); + let remove = true; + + if (Array.isArray(partialPath)) { + // recursively delete value tree, when no other keys exist + while (partialPath.length > 0) { + const lastKey = partialPath.splice(partialPath.length - 1, 1)[0]; + const statePath = [...this._path, partialPath]; + const stateVal = statePath.length > 0 ? get(stateTree, statePath) : stateTree; + + // if stateVal isn't an object, do nothing + if (!isPlainObject(stateVal)) return; + + if (remove) delete stateVal[lastKey]; + if (Object.keys(stateVal).length > 0) remove = false; + } + } + } + + private getDefault() { + return this.hasPath() ? undefined : {}; + } + + private setPath(path?: PersistedStatePath): string[] { + if (Array.isArray(path)) { + return path; + } + + if (isString(path)) { + return [...this.getIndex(path)]; + } + + return []; + } + + private hasPath() { + return this._path.length > 0; + } + + private setValue(key: PersistedStateKey, value: any, silent: boolean = false) { + const self = this; + let stateChanged = false; + const initialState = !this._initialized; + const keyPath = this.getIndex(key); + const hasKeyPath = keyPath.length > 0; + + // if this is the initial state value, save value as the default + if (initialState) { + this._changedState = {}; + if (!this.hasPath() && key === undefined) this._defaultState = value; + else this._defaultState = set({}, keyPath, value); + } + + if (!initialState) { + // no path and no key, set the whole state + if (!this.hasPath() && key === undefined) { + // compare changedState and new state, emit an event when different + stateChanged = !isEqual(this._changedState, value); + this._changedState = value; + this._mergedState = cloneDeep(value); + } else { + // check for changes at path, emit an event when different + const curVal = hasKeyPath ? this.get(keyPath) : this._mergedState; + stateChanged = !isEqual(curVal, value); + + // arrays are merge by index, not desired - ensure they are replaced + if (Array.isArray(get(this._mergedState, keyPath))) { + if (hasKeyPath) { + set(this._mergedState, keyPath, undefined); + } else { + this._mergedState = undefined; + } + } + + if (hasKeyPath) { + set(this._changedState, keyPath, value); + } else { + this._changedState = isPlainObject(value) ? value : {}; + } + } + } + + // update the merged state value + const targetObj = this._mergedState || cloneDeep(this._defaultState); + const sourceObj = merge({}, this._changedState); + + // handler arguments are (targetValue, sourceValue, key, target, source) + const mergeMethod = function(targetValue: any, sourceValue: any, mergeKey: string) { + // if not initial state, skip default merge method (ie. return value, see note below) + if (!initialState && isEqual(keyPath, self.getIndex(mergeKey))) { + // use the sourceValue or fall back to targetValue + return sourceValue === undefined ? targetValue : sourceValue; + } + }; + + // If `mergeMethod` is provided it is invoked to produce the merged values of the + // destination and source properties. + // If `mergeMethod` returns `undefined` the default merging method is used + this._mergedState = merge(targetObj, sourceObj, mergeMethod); + + // sanity check; verify that there are actually changes + if (isEqual(this._mergedState, this._defaultState)) this._changedState = {}; + + if (!silent && stateChanged) this.emit('change', key); + + return this; + } +} diff --git a/src/legacy/ui/public/persisted_state/persisted_state_provider.test.ts b/src/plugins/visualizations/public/persisted_state/persisted_state_provider.test.ts similarity index 96% rename from src/legacy/ui/public/persisted_state/persisted_state_provider.test.ts rename to src/plugins/visualizations/public/persisted_state/persisted_state_provider.test.ts index f14215002cf8f2..76446a3f44861b 100644 --- a/src/legacy/ui/public/persisted_state/persisted_state_provider.test.ts +++ b/src/plugins/visualizations/public/persisted_state/persisted_state_provider.test.ts @@ -17,7 +17,6 @@ * under the License. */ -import { PersistedStateError } from './errors'; import { PersistedState } from './persisted_state'; describe('Persisted State Provider', () => { @@ -47,7 +46,7 @@ describe('Persisted State Provider', () => { }); test('should throw if given an invalid value', () => { - expect(() => new PersistedState('bananas')).toThrow(PersistedStateError); + expect(() => new PersistedState('bananas')).toThrow(Error); }); }); @@ -224,13 +223,13 @@ describe('Persisted State Provider', () => { describe('internal state tracking', () => { test('should be an empty object', () => { const persistedState = new PersistedState(); - expect(persistedState._defaultState).toEqual({}); + expect(persistedState).toHaveProperty('_defaultState', {}); }); test('should store the default state value', () => { const val = { one: 1, two: 2 }; const persistedState = new PersistedState(val); - expect(persistedState._defaultState).toEqual(val); + expect(persistedState).toHaveProperty('_defaultState', val); }); test('should keep track of changes', () => { @@ -238,8 +237,8 @@ describe('Persisted State Provider', () => { const persistedState = new PersistedState(val); persistedState.set('two', 22); - expect(persistedState._defaultState).toEqual(val); - expect(persistedState._changedState).toEqual({ two: 22 }); + expect(persistedState).toHaveProperty('_defaultState', val); + expect(persistedState).toHaveProperty('_changedState', { two: 22 }); }); }); diff --git a/x-pack/legacy/plugins/monitoring/public/np_imports/legacy_imports.ts b/x-pack/legacy/plugins/monitoring/public/np_imports/legacy_imports.ts index ea29ac95eb03f3..a2ebe8231456f7 100644 --- a/x-pack/legacy/plugins/monitoring/public/np_imports/legacy_imports.ts +++ b/x-pack/legacy/plugins/monitoring/public/np_imports/legacy_imports.ts @@ -17,7 +17,6 @@ export { StateManagementConfigProvider } from 'ui/state_management/config_provid export { AppStateProvider } from 'ui/state_management/app_state'; // @ts-ignore export { EventsProvider } from 'ui/events'; -export { PersistedState } from 'ui/persisted_state'; // @ts-ignore export { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url'; export { registerTimefilterWithGlobalStateFactory } from 'ui/timefilter/setup_router';