Skip to content

Commit 5c69049

Browse files
author
Stacey Gammon
committed
Add direct access link registry and dashboard impl and use in ML (#57496)
* 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
1 parent 60f6131 commit 5c69049

File tree

32 files changed

+1463
-45
lines changed

32 files changed

+1463
-45
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
## Access links examples
2+
3+
This example app shows how to:
4+
- Register a direct access link generator.
5+
- Handle migration of legacy generators into a new one.
6+
7+
To run this example, use the command `yarn start --run-examples`. Navigate to the access links explorer app
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"id": "urlGeneratorsExamples",
3+
"version": "0.0.1",
4+
"kibanaVersion": "kibana",
5+
"configPath": ["url_generators_examples"],
6+
"server": false,
7+
"ui": true,
8+
"requiredPlugins": ["share"],
9+
"optionalPlugins": []
10+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "url_generators_examples",
3+
"version": "1.0.0",
4+
"main": "target/examples/url_generators_examples",
5+
"kibana": {
6+
"version": "kibana",
7+
"templateVersion": "1.0.0"
8+
},
9+
"license": "Apache-2.0",
10+
"scripts": {
11+
"kbn": "node ../../scripts/kbn.js",
12+
"build": "rm -rf './target' && tsc"
13+
},
14+
"devDependencies": {
15+
"typescript": "3.5.3"
16+
}
17+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import React from 'react';
21+
import ReactDOM from 'react-dom';
22+
23+
import { EuiPageBody } from '@elastic/eui';
24+
import { EuiPageContent } from '@elastic/eui';
25+
import { EuiPageContentBody } from '@elastic/eui';
26+
import { Route, Switch, Redirect, Router, useLocation } from 'react-router-dom';
27+
import { createBrowserHistory } from 'history';
28+
import { EuiText } from '@elastic/eui';
29+
import { AppMountParameters } from '../../../src/core/public';
30+
31+
function useQuery() {
32+
const { search } = useLocation();
33+
const params = React.useMemo(() => new URLSearchParams(search), [search]);
34+
return params;
35+
}
36+
37+
interface HelloPageProps {
38+
firstName: string;
39+
lastName: string;
40+
}
41+
42+
const HelloPage = ({ firstName, lastName }: HelloPageProps) => (
43+
<EuiText>{`Hello ${firstName} ${lastName}`}</EuiText>
44+
);
45+
46+
export const Routes: React.FC<{}> = () => {
47+
const query = useQuery();
48+
49+
return (
50+
<EuiPageBody>
51+
<EuiPageContent>
52+
<EuiPageContentBody>
53+
<Switch>
54+
<Route path="/hello">
55+
<HelloPage
56+
firstName={query.get('firstName') || ''}
57+
lastName={query.get('lastName') || ''}
58+
/>
59+
</Route>
60+
<Redirect from="/" to="/hello" />
61+
</Switch>
62+
</EuiPageContentBody>
63+
</EuiPageContent>
64+
</EuiPageBody>
65+
);
66+
};
67+
68+
export const LinksExample: React.FC<{
69+
appBasePath: string;
70+
}> = props => {
71+
const history = React.useMemo(
72+
() =>
73+
createBrowserHistory({
74+
basename: props.appBasePath,
75+
}),
76+
[props.appBasePath]
77+
);
78+
return (
79+
<Router history={history}>
80+
<Routes />
81+
</Router>
82+
);
83+
};
84+
85+
export const renderApp = (props: { appBasePath: string }, { element }: AppMountParameters) => {
86+
ReactDOM.render(<LinksExample {...props} />, element);
87+
88+
return () => ReactDOM.unmountComponentAtNode(element);
89+
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import { AccessLinksExamplesPlugin } from './plugin';
21+
22+
export const plugin = () => new AccessLinksExamplesPlugin();
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import { SharePluginStart, SharePluginSetup } from '../../../src/plugins/share/public';
21+
import { Plugin, CoreSetup, AppMountParameters } from '../../../src/core/public';
22+
import {
23+
HelloLinkGeneratorState,
24+
createHelloPageLinkGenerator,
25+
LegacyHelloLinkGeneratorState,
26+
HELLO_URL_GENERATOR_V1,
27+
HELLO_URL_GENERATOR,
28+
helloPageLinkGeneratorV1,
29+
} from './url_generator';
30+
31+
declare module '../../../src/plugins/share/public' {
32+
export interface UrlGeneratorStateMapping {
33+
[HELLO_URL_GENERATOR_V1]: LegacyHelloLinkGeneratorState;
34+
[HELLO_URL_GENERATOR]: HelloLinkGeneratorState;
35+
}
36+
}
37+
38+
interface StartDeps {
39+
share: SharePluginStart;
40+
}
41+
42+
interface SetupDeps {
43+
share: SharePluginSetup;
44+
}
45+
46+
const APP_ID = 'urlGeneratorsExamples';
47+
48+
export class AccessLinksExamplesPlugin implements Plugin<void, void, SetupDeps, StartDeps> {
49+
public setup(core: CoreSetup<StartDeps>, { share: { urlGenerators } }: SetupDeps) {
50+
urlGenerators.registerUrlGenerator(
51+
createHelloPageLinkGenerator(async () => ({
52+
appBasePath: (await core.getStartServices())[0].application.getUrlForApp(APP_ID),
53+
}))
54+
);
55+
56+
urlGenerators.registerUrlGenerator(helloPageLinkGeneratorV1);
57+
58+
core.application.register({
59+
id: APP_ID,
60+
title: 'Access links examples',
61+
async mount(params: AppMountParameters) {
62+
const { renderApp } = await import('./app');
63+
return renderApp(
64+
{
65+
appBasePath: params.appBasePath,
66+
},
67+
params
68+
);
69+
},
70+
});
71+
}
72+
73+
public start() {}
74+
75+
public stop() {}
76+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
import url from 'url';
20+
import { UrlGeneratorState, UrlGeneratorsDefinition } from '../../../src/plugins/share/public';
21+
22+
/**
23+
* The name of the latest variable can always stay the same so code that
24+
* uses this link generator statically will switch to the latest version.
25+
* Typescript will warn the developer if incorrect state is being passed
26+
* down.
27+
*/
28+
export const HELLO_URL_GENERATOR = 'HELLO_URL_GENERATOR_V2';
29+
30+
export interface HelloLinkState {
31+
firstName: string;
32+
lastName: string;
33+
}
34+
35+
export type HelloLinkGeneratorState = UrlGeneratorState<HelloLinkState>;
36+
37+
export const createHelloPageLinkGenerator = (
38+
getStartServices: () => Promise<{ appBasePath: string }>
39+
): UrlGeneratorsDefinition<typeof HELLO_URL_GENERATOR> => ({
40+
id: HELLO_URL_GENERATOR,
41+
createUrl: async state => {
42+
const startServices = await getStartServices();
43+
const appBasePath = startServices.appBasePath;
44+
const parsedUrl = url.parse(window.location.href);
45+
46+
return url.format({
47+
protocol: parsedUrl.protocol,
48+
host: parsedUrl.host,
49+
pathname: `${appBasePath}/hello`,
50+
query: {
51+
...state,
52+
},
53+
});
54+
},
55+
});
56+
57+
/**
58+
* The name of this legacy generator id changes, but the *value* stays the same.
59+
*/
60+
export const HELLO_URL_GENERATOR_V1 = 'HELLO_URL_GENERATOR';
61+
62+
export interface HelloLinkStateV1 {
63+
name: string;
64+
}
65+
66+
export type LegacyHelloLinkGeneratorState = UrlGeneratorState<
67+
HelloLinkStateV1,
68+
typeof HELLO_URL_GENERATOR,
69+
HelloLinkState
70+
>;
71+
72+
export const helloPageLinkGeneratorV1: UrlGeneratorsDefinition<typeof HELLO_URL_GENERATOR_V1> = {
73+
id: HELLO_URL_GENERATOR_V1,
74+
isDeprecated: true,
75+
migrate: async state => {
76+
return { id: HELLO_URL_GENERATOR, state: { firstName: state.name, lastName: '' } };
77+
},
78+
};
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"extends": "../../tsconfig.json",
3+
"compilerOptions": {
4+
"outDir": "./target",
5+
"skipLibCheck": true
6+
},
7+
"include": [
8+
"index.ts",
9+
"public/**/*.ts",
10+
"public/**/*.tsx",
11+
"server/**/*.ts",
12+
"../../typings/**/*"
13+
],
14+
"exclude": []
15+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
## Access links explorer
2+
3+
This example app shows how to:
4+
- Generate links to other applications
5+
- Generate dynamic links, when the target application is not known
6+
- Handle backward compatibility of urls
7+
8+
To run this example, use the command `yarn start --run-examples`.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"id": "urlGeneratorsExplorer",
3+
"version": "0.0.1",
4+
"kibanaVersion": "kibana",
5+
"configPath": ["url_generators_explorer"],
6+
"server": false,
7+
"ui": true,
8+
"requiredPlugins": ["share", "urlGeneratorsExamples"],
9+
"optionalPlugins": []
10+
}

0 commit comments

Comments
 (0)