Skip to content

Commit

Permalink
[State Management] Move url state_hashing utils to kibana_utils (#52280)
Browse files Browse the repository at this point in the history
Part of #44151,
Continuation of #51835,
Just moves existing state related url utils to kibana_utils plugin

Also fixes small regression introduced in #51835,
When sharing hashed url directly it should show error toast instead of full page fatal error
  • Loading branch information
Dosant authored Dec 6, 2019
1 parent ca55402 commit 881c836
Show file tree
Hide file tree
Showing 20 changed files with 120 additions and 32 deletions.
1 change: 1 addition & 0 deletions .i18nrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"kbnVislibVisTypes": "src/legacy/core_plugins/kbn_vislib_vis_types",
"kibana_react": "src/legacy/core_plugins/kibana_react",
"kibana-react": "src/plugins/kibana_react",
"kibana_utils": "src/plugins/kibana_utils",
"navigation": "src/legacy/core_plugins/navigation",
"newsfeed": "src/plugins/newsfeed",
"regionMap": "src/legacy/core_plugins/region_map",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,6 @@ export { confirmModalFactory } from 'ui/modals/confirm_modal';
export { configureAppAngularModule } from 'ui/legacy_compat';
export { stateMonitorFactory, StateMonitor } from 'ui/state_management/state_monitor_factory';
export { ensureDefaultIndexPattern } from 'ui/legacy_compat';
export { unhashUrl } from 'ui/state_management/state_hashing';
export { unhashUrl } from '../../../../../plugins/kibana_utils/public';
export { IInjector } from 'ui/chrome';
export { SavedObjectFinder } from 'ui/saved_objects/components/saved_object_finder';
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export { tabifyAggResponse } from 'ui/agg_response/tabify';
// @ts-ignore
export { vislibSeriesResponseHandlerProvider } from 'ui/vis/response_handlers/vislib';
export { ensureDefaultIndexPattern } from 'ui/legacy_compat';
export { unhashUrl } from 'ui/state_management/state_hashing';
export { unhashUrl } from '../../../../../plugins/kibana_utils/public';

// EXPORT types
export { Vis } from 'ui/vis';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import {
showSaveModal,
stateMonitorFactory,
subscribeWithScope,
unhashUrl,
unhashUrl
} from '../kibana_services';

const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export { KibanaParsedUrl } from 'ui/url/kibana_parsed_url';
export { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query';
export { subscribeWithScope } from 'ui/utils/subscribe_with_scope';
export { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal';
export { unhashUrl } from 'ui/state_management/state_hashing';
export { unhashUrl } from '../../../../../plugins/kibana_utils/public';
export {
Container,
Embeddable,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/

import chrome from 'ui/chrome';
import { hashUrl } from 'ui/state_management/state_hashing';
import { hashUrl } from '../../../../plugins/kibana_utils/public';
import uiRoutes from 'ui/routes';
import { fatalError } from 'ui/notify';

Expand Down
15 changes: 10 additions & 5 deletions src/legacy/ui/public/chrome/api/sub_url_hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,23 @@

import url from 'url';

import {
unhashUrl,
} from '../../state_management/state_hashing';
import { unhashUrl } from '../../../../../plugins/kibana_utils/public';
import { toastNotifications } from '../../notify/toasts';

export function registerSubUrlHooks(angularModule, internals) {
angularModule.run(($rootScope, Private, $location) => {
const subUrlRouteFilter = Private(SubUrlRouteFilterProvider);

function updateSubUrls() {
const urlWithHashes = window.location.href;
const urlWithStates = unhashUrl(urlWithHashes);
internals.trackPossibleSubUrl(urlWithStates);
let urlWithStates;
try {
urlWithStates = unhashUrl(urlWithHashes);
} catch (e) {
toastNotifications.addDanger(e.message);
}

internals.trackPossibleSubUrl(urlWithStates || urlWithHashes);
}

function onRouteChange($event) {
Expand Down
6 changes: 3 additions & 3 deletions src/legacy/ui/public/state_management/__tests__/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ import { toastNotifications } from '../../notify';
import * as FatalErrorNS from '../../notify/fatal_error';
import { StateProvider } from '../state';
import {
unhashQuery,
createStateHash,
isStateHash,
unhashQuery
} from '../state_hashing';
import { HashedItemStore } from '../../../../../plugins/kibana_utils/public';
HashedItemStore
} from '../../../../../plugins/kibana_utils/public';
import { StubBrowserStorage } from 'test_utils/stub_browser_storage';
import { EventsProvider } from '../../events';

Expand Down
6 changes: 1 addition & 5 deletions src/legacy/ui/public/state_management/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,7 @@ import { fatalError, toastNotifications } from '../notify';
import './config_provider';
import { createLegacyClass } from '../utils/legacy_class';
import { callEach } from '../utils/function';
import { hashedItemStore } from '../../../../plugins/kibana_utils/public';
import {
createStateHash,
isStateHash
} from './state_hashing';
import { hashedItemStore, isStateHash, createStateHash } from '../../../../plugins/kibana_utils/public';

export function StateProvider(Private, $rootScope, $location, stateManagementConfig, config, kbnUrl, $injector) {
const Events = Private(EventsProvider);
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/kibana_utils/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ export * from './errors';
export * from './field_mapping';
export * from './storage';
export * from './storage/hashed_item_store';
export * from './state_management/state_hash';
export * from './state_management/url';
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,4 @@
* under the License.
*/

export { hashUrl, unhashUrl, hashQuery, unhashQuery } from './hash_unhash_url';
export { createStateHash, isStateHash } from './state_hash';
export * from './state_hash';
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@
*/

import { encode as encodeRison } from 'rison-node';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { mockStorage } from '../../../../../plugins/kibana_utils/public/storage/hashed_item_store/mock';
import { createStateHash, isStateHash } from '../state_hashing';
import { mockStorage } from '../../storage/hashed_item_store/mock';
import { createStateHash, isStateHash } from './state_hash';

describe('stateHash', () => {
beforeEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/

import { Sha256 } from '../../../../../core/public/utils';
import { hashedItemStore } from '../../../../../plugins/kibana_utils/public';
import { hashedItemStore } from '../../storage/hashed_item_store';

// This prefix is used to identify hash strings that have been encoded in the URL.
const HASH_PREFIX = 'h@';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
* under the License.
*/

// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { mockStorage } from '../../../../../plugins/kibana_utils/public/storage/hashed_item_store/mock';
import { HashedItemStore } from '../../../../../plugins/kibana_utils/public';
import { mockStorage } from '../../storage/hashed_item_store/mock';
import { HashedItemStore } from '../../storage/hashed_item_store';
import { hashUrl, unhashUrl } from './hash_unhash_url';

describe('hash unhash url', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import rison, { RisonObject } from 'rison-node';
import { stringify as stringifyQueryString } from 'querystring';
import encodeUriQuery from 'encode-uri-query';
import { format as formatUrl, parse as parseUrl } from 'url';
import { hashedItemStore } from '../../../../../plugins/kibana_utils/public';
import { createStateHash, isStateHash } from './state_hash';
import { hashedItemStore } from '../../storage/hashed_item_store';
import { createStateHash, isStateHash } from '../state_hash';

export type IParsedUrlQuery = Record<string, any>;

Expand Down Expand Up @@ -98,7 +98,7 @@ export function retrieveState(stateHash: string): RisonObject {
const json = hashedItemStore.getItem(stateHash);
const throwUnableToRestoreUrlError = () => {
throw new Error(
i18n.translate('common.ui.stateManagement.unableToRestoreUrlErrorMessage', {
i18n.translate('kibana_utils.stateManagement.url.unableToRestoreUrlErrorMessage', {
defaultMessage:
'Unable to completely restore the URL, be sure to use the share functionality.',
})
Expand All @@ -125,7 +125,7 @@ export function persistState(state: RisonObject): string {
if (isItemSet) return hash;
// If we ran out of space trying to persist the state, notify the user.
const message = i18n.translate(
'common.ui.stateManagement.unableToStoreHistoryInSessionErrorMessage',
'kibana_utils.stateManagement.url.unableToStoreHistoryInSessionErrorMessage',
{
defaultMessage:
'Kibana is unable to store history items in your session ' +
Expand Down
20 changes: 20 additions & 0 deletions src/plugins/kibana_utils/public/state_management/url/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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 * from './hash_unhash_url';
24 changes: 24 additions & 0 deletions test/typings/encode_uri_query.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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.
*/

declare module 'encode-uri-query' {
function encodeUriQuery(query: string, usePercentageSpace?: boolean): string;
// eslint-disable-next-line import/no-default-export
export default encodeUriQuery;
}
39 changes: 39 additions & 0 deletions test/typings/rison_node.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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.
*/

declare module 'rison-node' {
export type RisonValue = null | boolean | number | string | RisonObject | RisonArray;

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface RisonArray extends Array<RisonValue> {}

export interface RisonObject {
[key: string]: RisonValue;
}

export const decode: (input: string) => RisonValue;

// eslint-disable-next-line @typescript-eslint/camelcase
export const decode_object: (input: string) => RisonObject;

export const encode: <Input extends RisonValue>(input: Input) => string;

// eslint-disable-next-line @typescript-eslint/camelcase
export const encode_object: <Input extends RisonObject>(input: Input) => string;
}
4 changes: 3 additions & 1 deletion x-pack/plugins/translations/translations/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,8 @@
"kibana-react.savedObjects.saveModal.saveButtonLabel": "保存",
"kibana-react.savedObjects.saveModal.saveTitle": "{objectType} を保存",
"kibana-react.savedObjects.saveModal.titleLabel": "タイトル",
"kibana_utils.stateManagement.url.unableToRestoreUrlErrorMessage": "URL を完全に復元できません。共有機能を使用していることを確認してください。",
"kibana_utils.stateManagement.url.unableToStoreHistoryInSessionErrorMessage": "セッションがいっぱいで安全に削除できるアイテムが見つからないため、Kibana は履歴アイテムを保存できません。\n\nこれは大抵新規タブに移動することで解決されますが、より大きな問題が原因である可能性もあります。このメッセージが定期的に表示される場合は、{gitHubIssuesUrl} で問題を報告してください。",
"inspector.closeButton": "インスペクターを閉じる",
"inspector.reqTimestampDescription": "リクエストの開始が記録された時刻です",
"inspector.reqTimestampKey": "リクエストのタイムスタンプ",
Expand Down Expand Up @@ -12750,4 +12752,4 @@
"xpack.licensing.check.errorUnavailableMessage": "現在ライセンス情報が利用できないため {pluginName} を使用できません。",
"xpack.licensing.check.errorUnsupportedMessage": "ご使用の {licenseType} ライセンスは {pluginName} をサポートしていません。ライセンスをアップグレードしてください。"
}
}
}
2 changes: 2 additions & 0 deletions x-pack/plugins/translations/translations/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,8 @@
"kibana-react.savedObjects.saveModal.saveButtonLabel": "保存",
"kibana-react.savedObjects.saveModal.saveTitle": "保存 {objectType}",
"kibana-react.savedObjects.saveModal.titleLabel": "标题",
"kibana_utils.stateManagement.url.unableToRestoreUrlErrorMessage": "无法完整还原 URL,确保使用共享功能。",
"kibana_utils.stateManagement.url.unableToStoreHistoryInSessionErrorMessage": "Kibana 无法将历史记录项存储在您的会话中,因为其已满,并且似乎没有任何可安全删除的项。\n\n通常可通过移至新的标签页来解决此问题,但这会导致更大的问题。如果您有规律地看到此消息,请在 {gitHubIssuesUrl} 提交问题。",
"inspector.closeButton": "关闭检查器",
"inspector.reqTimestampDescription": "记录请求启动的时间",
"inspector.reqTimestampKey": "请求时间戳",
Expand Down

0 comments on commit 881c836

Please sign in to comment.