Skip to content

Commit

Permalink
[State Management] State syncing utilities (#53582) (#54454)
Browse files Browse the repository at this point in the history
Today, apps rely on AppState and GlobalState in the ui/state_management module to deal with internal (app) and shared (global) state. These classes give apps an ability to read/write state, when is then synced to the URL as well as sessionStorage. They also react to changes in the URL and automatically update state & emit events when changes occur.

This PR introduces new state synching utilities, which together with state containers src/plugins/kibana_utils/public/state_containers will be a replacement for AppState and GlobalState in New Platform.

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
Dosant and elasticmachine committed Jan 13, 2020
1 parent 8636011 commit 5f52cf0
Show file tree
Hide file tree
Showing 56 changed files with 2,790 additions and 168 deletions.
10 changes: 10 additions & 0 deletions examples/state_containers_examples/kibana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"id": "stateContainersExamples",
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["state_containers_examples"],
"server": false,
"ui": true,
"requiredPlugins": [],
"optionalPlugins": []
}
17 changes: 17 additions & 0 deletions examples/state_containers_examples/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "state_containers_examples",
"version": "1.0.0",
"main": "target/examples/state_containers_examples",
"kibana": {
"version": "kibana",
"templateVersion": "1.0.0"
},
"license": "Apache-2.0",
"scripts": {
"kbn": "node ../../scripts/kbn.js",
"build": "rm -rf './target' && tsc"
},
"devDependencies": {
"typescript": "3.7.2"
}
}
69 changes: 69 additions & 0 deletions examples/state_containers_examples/public/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* 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 { AppMountParameters } from 'kibana/public';
import ReactDOM from 'react-dom';
import React from 'react';
import { createHashHistory, createBrowserHistory } from 'history';
import { TodoAppPage } from './todo';

export interface AppOptions {
appInstanceId: string;
appTitle: string;
historyType: History;
}

export enum History {
Browser,
Hash,
}

export const renderApp = (
{ appBasePath, element }: AppMountParameters,
{ appInstanceId, appTitle, historyType }: AppOptions
) => {
const history =
historyType === History.Browser
? createBrowserHistory({ basename: appBasePath })
: createHashHistory();
ReactDOM.render(
<TodoAppPage
history={history}
appInstanceId={appInstanceId}
appTitle={appTitle}
appBasePath={appBasePath}
isInitialRoute={() => {
const stripTrailingSlash = (path: string) =>
path.charAt(path.length - 1) === '/' ? path.substr(0, path.length - 1) : path;
const currentAppUrl = stripTrailingSlash(history.createHref(history.location));
if (historyType === History.Browser) {
// browser history
const basePath = stripTrailingSlash(appBasePath);
return currentAppUrl === basePath && !history.location.search && !history.location.hash;
} else {
// hashed history
return currentAppUrl === '#' && !history.location.search;
}
}}
/>,
element
);

return () => ReactDOM.unmountComponentAtNode(element);
};
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
* 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;
}
import { StateContainersExamplesPlugin } from './plugin';

export const plugin = () => new StateContainersExamplesPlugin();
52 changes: 52 additions & 0 deletions examples/state_containers_examples/public/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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 { AppMountParameters, CoreSetup, Plugin } from 'kibana/public';

export class StateContainersExamplesPlugin implements Plugin {
public setup(core: CoreSetup) {
core.application.register({
id: 'state-containers-example-browser-history',
title: 'State containers example - browser history routing',
async mount(params: AppMountParameters) {
const { renderApp, History } = await import('./app');
return renderApp(params, {
appInstanceId: '1',
appTitle: 'Routing with browser history',
historyType: History.Browser,
});
},
});
core.application.register({
id: 'state-containers-example-hash-history',
title: 'State containers example - hash history routing',
async mount(params: AppMountParameters) {
const { renderApp, History } = await import('./app');
return renderApp(params, {
appInstanceId: '2',
appTitle: 'Routing with hash history',
historyType: History.Hash,
});
},
});
}

public start() {}
public stop() {}
}
Loading

0 comments on commit 5f52cf0

Please sign in to comment.