Skip to content

Commit

Permalink
Add direct access link registry and dashboard impl and use in ML (#57496
Browse files Browse the repository at this point in the history
)

* Add direct access link registry and dashboard impl and use in ML

* Add example plugin with migration example

* address code review comments

* Fixes, more code review updates

* Readme clean up

* add tests

* remove else

* Rename everything from DirectAccessLinkGenerator to the much short UrlGenerator. also fix the ml # thing and return a relative link from dashboard genrator

* add important text in bold

* Move url generators into share plugin

* add correct i18n prefix

* Fix timeRange url name

* make share plugin optional for dashboard

* fix code owners

* Use base UrlGeneratorState type, add comments

* Fix hash bug and add test that would have caught it
  • Loading branch information
stacey-gammon authored Mar 4, 2020
1 parent 455b2f5 commit 543481b
Show file tree
Hide file tree
Showing 33 changed files with 1,467 additions and 47 deletions.
6 changes: 4 additions & 2 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
# App
/x-pack/legacy/plugins/lens/ @elastic/kibana-app
/x-pack/legacy/plugins/graph/ @elastic/kibana-app
/src/plugins/share/ @elastic/kibana-app
/src/legacy/server/url_shortening/ @elastic/kibana-app
/src/legacy/server/sample_data/ @elastic/kibana-app
/src/legacy/core_plugins/kibana/public/dashboard/ @elastic/kibana-app
Expand All @@ -27,6 +26,7 @@
/src/plugins/kibana_legacy/ @elastic/kibana-app
/src/plugins/timelion/ @elastic/kibana-app
/src/plugins/dev_tools/ @elastic/kibana-app
/src/plugins/dashboard_embeddable_container/ @elastic/kibana-app

# App Architecture
/packages/kbn-interpreter/ @elastic/kibana-app-arch
Expand All @@ -42,7 +42,6 @@
/src/legacy/core_plugins/visualizations/ @elastic/kibana-app-arch
/src/legacy/server/index_patterns/ @elastic/kibana-app-arch
/src/plugins/bfetch/ @elastic/kibana-app-arch
/src/plugins/dashboard_embeddable_container/ @elastic/kibana-app-arch
/src/plugins/data/ @elastic/kibana-app-arch
/src/plugins/embeddable/ @elastic/kibana-app-arch
/src/plugins/expressions/ @elastic/kibana-app-arch
Expand All @@ -53,6 +52,9 @@
/src/plugins/navigation/ @elastic/kibana-app-arch
/src/plugins/ui_actions/ @elastic/kibana-app-arch
/src/plugins/visualizations/ @elastic/kibana-app-arch
/src/plugins/share/ @elastic/kibana-app-arch
/examples/url_generators_examples/ @elastic/kibana-app-arch
/examples/url_generators_explorer/ @elastic/kibana-app-arch
/x-pack/plugins/advanced_ui_actions/ @elastic/kibana-app-arch
/x-pack/plugins/drilldowns/ @elastic/kibana-app-arch

Expand Down
7 changes: 7 additions & 0 deletions examples/url_generators_examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## Access links examples

This example app shows how to:
- Register a direct access link generator.
- Handle migration of legacy generators into a new one.

To run this example, use the command `yarn start --run-examples`. Navigate to the access links explorer app
10 changes: 10 additions & 0 deletions examples/url_generators_examples/kibana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"id": "urlGeneratorsExamples",
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["url_generators_examples"],
"server": false,
"ui": true,
"requiredPlugins": ["share"],
"optionalPlugins": []
}
17 changes: 17 additions & 0 deletions examples/url_generators_examples/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "url_generators_examples",
"version": "1.0.0",
"main": "target/examples/url_generators_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.5.3"
}
}
89 changes: 89 additions & 0 deletions examples/url_generators_examples/public/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* 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 React from 'react';
import ReactDOM from 'react-dom';

import { EuiPageBody } from '@elastic/eui';
import { EuiPageContent } from '@elastic/eui';
import { EuiPageContentBody } from '@elastic/eui';
import { Route, Switch, Redirect, Router, useLocation } from 'react-router-dom';
import { createBrowserHistory } from 'history';
import { EuiText } from '@elastic/eui';
import { AppMountParameters } from '../../../src/core/public';

function useQuery() {
const { search } = useLocation();
const params = React.useMemo(() => new URLSearchParams(search), [search]);
return params;
}

interface HelloPageProps {
firstName: string;
lastName: string;
}

const HelloPage = ({ firstName, lastName }: HelloPageProps) => (
<EuiText>{`Hello ${firstName} ${lastName}`}</EuiText>
);

export const Routes: React.FC<{}> = () => {
const query = useQuery();

return (
<EuiPageBody>
<EuiPageContent>
<EuiPageContentBody>
<Switch>
<Route path="/hello">
<HelloPage
firstName={query.get('firstName') || ''}
lastName={query.get('lastName') || ''}
/>
</Route>
<Redirect from="/" to="/hello" />
</Switch>
</EuiPageContentBody>
</EuiPageContent>
</EuiPageBody>
);
};

export const LinksExample: React.FC<{
appBasePath: string;
}> = props => {
const history = React.useMemo(
() =>
createBrowserHistory({
basename: props.appBasePath,
}),
[props.appBasePath]
);
return (
<Router history={history}>
<Routes />
</Router>
);
};

export const renderApp = (props: { appBasePath: string }, { element }: AppMountParameters) => {
ReactDOM.render(<LinksExample {...props} />, element);

return () => ReactDOM.unmountComponentAtNode(element);
};
22 changes: 22 additions & 0 deletions examples/url_generators_examples/public/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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 { AccessLinksExamplesPlugin } from './plugin';

export const plugin = () => new AccessLinksExamplesPlugin();
76 changes: 76 additions & 0 deletions examples/url_generators_examples/public/plugin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* 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 { SharePluginStart, SharePluginSetup } from '../../../src/plugins/share/public';
import { Plugin, CoreSetup, AppMountParameters } from '../../../src/core/public';
import {
HelloLinkGeneratorState,
createHelloPageLinkGenerator,
LegacyHelloLinkGeneratorState,
HELLO_URL_GENERATOR_V1,
HELLO_URL_GENERATOR,
helloPageLinkGeneratorV1,
} from './url_generator';

declare module '../../../src/plugins/share/public' {
export interface UrlGeneratorStateMapping {
[HELLO_URL_GENERATOR_V1]: LegacyHelloLinkGeneratorState;
[HELLO_URL_GENERATOR]: HelloLinkGeneratorState;
}
}

interface StartDeps {
share: SharePluginStart;
}

interface SetupDeps {
share: SharePluginSetup;
}

const APP_ID = 'urlGeneratorsExamples';

export class AccessLinksExamplesPlugin implements Plugin<void, void, SetupDeps, StartDeps> {
public setup(core: CoreSetup<StartDeps>, { share: { urlGenerators } }: SetupDeps) {
urlGenerators.registerUrlGenerator(
createHelloPageLinkGenerator(async () => ({
appBasePath: (await core.getStartServices())[0].application.getUrlForApp(APP_ID),
}))
);

urlGenerators.registerUrlGenerator(helloPageLinkGeneratorV1);

core.application.register({
id: APP_ID,
title: 'Access links examples',
async mount(params: AppMountParameters) {
const { renderApp } = await import('./app');
return renderApp(
{
appBasePath: params.appBasePath,
},
params
);
},
});
}

public start() {}

public stop() {}
}
78 changes: 78 additions & 0 deletions examples/url_generators_examples/public/url_generator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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 url from 'url';
import { UrlGeneratorState, UrlGeneratorsDefinition } from '../../../src/plugins/share/public';

/**
* The name of the latest variable can always stay the same so code that
* uses this link generator statically will switch to the latest version.
* Typescript will warn the developer if incorrect state is being passed
* down.
*/
export const HELLO_URL_GENERATOR = 'HELLO_URL_GENERATOR_V2';

export interface HelloLinkState {
firstName: string;
lastName: string;
}

export type HelloLinkGeneratorState = UrlGeneratorState<HelloLinkState>;

export const createHelloPageLinkGenerator = (
getStartServices: () => Promise<{ appBasePath: string }>
): UrlGeneratorsDefinition<typeof HELLO_URL_GENERATOR> => ({
id: HELLO_URL_GENERATOR,
createUrl: async state => {
const startServices = await getStartServices();
const appBasePath = startServices.appBasePath;
const parsedUrl = url.parse(window.location.href);

return url.format({
protocol: parsedUrl.protocol,
host: parsedUrl.host,
pathname: `${appBasePath}/hello`,
query: {
...state,
},
});
},
});

/**
* The name of this legacy generator id changes, but the *value* stays the same.
*/
export const HELLO_URL_GENERATOR_V1 = 'HELLO_URL_GENERATOR';

export interface HelloLinkStateV1 {
name: string;
}

export type LegacyHelloLinkGeneratorState = UrlGeneratorState<
HelloLinkStateV1,
typeof HELLO_URL_GENERATOR,
HelloLinkState
>;

export const helloPageLinkGeneratorV1: UrlGeneratorsDefinition<typeof HELLO_URL_GENERATOR_V1> = {
id: HELLO_URL_GENERATOR_V1,
isDeprecated: true,
migrate: async state => {
return { id: HELLO_URL_GENERATOR, state: { firstName: state.name, lastName: '' } };
},
};
15 changes: 15 additions & 0 deletions examples/url_generators_examples/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./target",
"skipLibCheck": true
},
"include": [
"index.ts",
"public/**/*.ts",
"public/**/*.tsx",
"server/**/*.ts",
"../../typings/**/*"
],
"exclude": []
}
8 changes: 8 additions & 0 deletions examples/url_generators_explorer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## Access links explorer

This example app shows how to:
- Generate links to other applications
- Generate dynamic links, when the target application is not known
- Handle backward compatibility of urls

To run this example, use the command `yarn start --run-examples`.
10 changes: 10 additions & 0 deletions examples/url_generators_explorer/kibana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"id": "urlGeneratorsExplorer",
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["url_generators_explorer"],
"server": false,
"ui": true,
"requiredPlugins": ["share", "urlGeneratorsExamples"],
"optionalPlugins": []
}
17 changes: 17 additions & 0 deletions examples/url_generators_explorer/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "url_generators_explorer",
"version": "1.0.0",
"main": "target/examples/url_generators_explorer",
"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.5.3"
}
}
Loading

0 comments on commit 543481b

Please sign in to comment.