Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UI] Getting started page for hosted pipelines #2935

Merged
merged 9 commits into from
Jan 31, 2020
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 29 additions & 10 deletions frontend/server/app.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { Storage as GCSStorage } from '@google-cloud/storage';
import { UIServer } from './app';
import { loadConfigs } from './configs';
import * as minioHelper from './minio-helper';
import { getTensorboardInstance } from './k8s-helper';

jest.mock('minio');
jest.mock('node-fetch');
Expand All @@ -46,15 +45,6 @@ describe('UIServer apis', () => {
</script>
<script id="kubeflow-client-placeholder"></script>
</head>
</html>`;
const expectedIndexHtml = `
<html>
<head>
<script>
window.KFP_FLAGS.DEPLOYMENT="KUBEFLOW"
</script>
<script id="kubeflow-client-placeholder" src="/dashboard_lib.bundle.js"></script>
</head>
</html>`;

beforeAll(() => {
Expand Down Expand Up @@ -92,6 +82,15 @@ describe('UIServer apis', () => {
});

it('responds with a modified index.html if it is a kubeflow deployment', done => {
const expectedIndexHtml = `
<html>
<head>
<script>
window.KFP_FLAGS.DEPLOYMENT="KUBEFLOW"
</script>
<script id="kubeflow-client-placeholder" src="/dashboard_lib.bundle.js"></script>
</head>
</html>`;
const configs = loadConfigs(argv, { DEPLOYMENT: 'kubeflow' });
app = new UIServer(configs);

Expand All @@ -101,6 +100,26 @@ describe('UIServer apis', () => {
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(200, expectedIndexHtml, done);
});

it('responds with flag DEPLOYMENT=MARKETPLACE if it is a marketplace deployment', done => {
const expectedIndexHtml = `
<html>
<head>
<script>
window.KFP_FLAGS.DEPLOYMENT="MARKETPLACE"
</script>
<script id="kubeflow-client-placeholder"></script>
</head>
</html>`;
const configs = loadConfigs(argv, { DEPLOYMENT: 'marketplace' });
app = new UIServer(configs);

const request = requests(app.start());
request
.get('/')
.expect('Content-Type', 'text/html; charset=utf-8')
.expect(200, expectedIndexHtml, done);
});
});

describe('/apis/v1beta1/healthz', () => {
Expand Down
5 changes: 4 additions & 1 deletion frontend/server/configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const apiVersionPrefix = `apis/${apiVersion}`;
export enum Deployments {
NOT_SPECIFIED = 'NOT_SPECIFIED',
KUBEFLOW = 'KUBEFLOW',
MARKETPLACE = 'MARKETPLACE',
}

/** converts string to bool */
Expand Down Expand Up @@ -132,8 +133,10 @@ export function loadConfigs(
apiVersionPrefix,
basePath: BASEPATH,
deployment:
DEPLOYMENT_STR.toUpperCase() === 'KUBEFLOW'
DEPLOYMENT_STR.toUpperCase() === Deployments.KUBEFLOW
? Deployments.KUBEFLOW
: DEPLOYMENT_STR.toUpperCase() === Deployments.MARKETPLACE
? Deployments.MARKETPLACE
: Deployments.NOT_SPECIFIED,
port,
staticDir,
Expand Down
3 changes: 3 additions & 0 deletions frontend/server/handlers/index-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,8 @@ function replaceRuntimeContent(content: string | undefined, deployment: Deployme
`<script id="kubeflow-client-placeholder" src="/dashboard_lib.bundle.js"></script>`,
);
}
if (content && deployment === Deployments.MARKETPLACE) {
return content.replace(DEFAULT_FLAG, 'window.KFP_FLAGS.DEPLOYMENT="MARKETPLACE"');
}
return content;
}
2 changes: 1 addition & 1 deletion frontend/src/atoms/ExternalLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ const css = stylesheet({

export const ExternalLink: React.FC<
DetailedHTMLProps<AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>
> = props => <a {...props} className={css.link} target='_blank' rel='noreferrer noopener' />;
> = props => <a {...props} className={css.link} target='_blank' rel='noopener' />;
9 changes: 8 additions & 1 deletion frontend/src/components/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import { Route, Switch, Redirect } from 'react-router-dom';
import { classes, stylesheet } from 'typestyle';
import { commonCss } from '../Css';
import NewPipelineVersion from '../pages/NewPipelineVersion';
import { GettingStarted } from '../pages/GettingStarted';
import { KFP_FLAGS, Deployments } from '../lib/Flags';

export type RouteConfig = { path: string; Component: React.ComponentType<any>; view?: any };

Expand Down Expand Up @@ -102,6 +104,7 @@ export const RoutePage = {
RECURRING_RUN: `/recurringrun/details/:${RouteParams.runId}`,
RUNS: '/runs',
RUN_DETAILS: `/runs/details/:${RouteParams.runId}`,
START: '/start',
};

export const RoutePageFactory = {
Expand Down Expand Up @@ -139,9 +142,13 @@ export interface RouterProps {
configs?: RouteConfig[]; // only used in tests
}

const DEFAULT_ROUTE =
KFP_FLAGS.DEPLOYMENT === Deployments.MARKETPLACE ? RoutePage.START : RoutePage.PIPELINES;

// This component is made as a wrapper to separate toolbar state for different pages.
const Router: React.FC<RouterProps> = ({ configs }) => {
const routes: RouteConfig[] = configs || [
{ path: RoutePage.START, Component: GettingStarted },
{ path: RoutePage.ARCHIVE, Component: Archive },
{ path: RoutePage.ARTIFACTS, Component: ArtifactList },
{ path: RoutePage.ARTIFACT_DETAILS, Component: ArtifactDetails },
Expand Down Expand Up @@ -170,7 +177,7 @@ const Router: React.FC<RouterProps> = ({ configs }) => {
<Route
exact={true}
path={'/'}
render={({ ...props }) => <Redirect to={RoutePage.PIPELINES} {...props} />}
render={({ ...props }) => <Redirect to={DEFAULT_ROUTE} {...props} />}
/>

{/* Normal routes */}
Expand Down
34 changes: 34 additions & 0 deletions frontend/src/components/SideNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { RouterProps } from 'react-router';
import { classes, stylesheet } from 'typestyle';
import { fontsize, commonCss } from '../Css';
import { logger } from '../lib/Utils';
import { KFP_FLAGS, Deployments } from '../lib/Flags';

export const sideNavColors = {
bg: '#f8fafb',
Expand Down Expand Up @@ -267,6 +268,39 @@ export default class SideNav extends React.Component<SideNavProps, SideNavState>
)}
>
<div style={{ flexGrow: 1 }}>
{KFP_FLAGS.DEPLOYMENT === Deployments.MARKETPLACE && (
<>
<div
className={classes(
css.indicator,
!page.startsWith(RoutePage.START) && css.indicatorHidden,
)}
/>
<Tooltip
title={'Getting Started'}
enterDelay={300}
placement={'right-start'}
disableFocusListener={!collapsed}
disableHoverListener={!collapsed}
disableTouchListener={!collapsed}
>
<Link id='gettingStartedBtn' to={RoutePage.START} className={commonCss.unstyled}>
<Button
className={classes(
css.button,
page.startsWith(RoutePage.START) && css.active,
collapsed && css.collapsedButton,
)}
>
<DescriptionIcon />
<span className={classes(collapsed && css.collapsedLabel, css.label)}>
Getting Started
</span>
</Button>
</Link>
</Tooltip>
</>
)}
<div
className={classes(
css.indicator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ exports[`Description When in inline mode renders markdown link 1`] = `
<a
class="link"
href="https://www.google.com"
rel="noreferrer noopener"
rel="noopener"
target="_blank"
>
google
Expand Down Expand Up @@ -39,7 +39,7 @@ exports[`Description When in inline mode renders raw link 1`] = `
<a
class="link"
href="https://www.google.com"
rel="noreferrer noopener"
rel="noopener"
target="_blank"
>
https://www.google.com
Expand All @@ -52,7 +52,7 @@ exports[`Description When in normal mode renders markdown link 1`] = `
<a
class="link"
href="https://www.google.com"
rel="noreferrer noopener"
rel="noopener"
target="_blank"
>
google
Expand Down Expand Up @@ -91,7 +91,7 @@ exports[`Description When in normal mode renders raw link 1`] = `
<a
class="link"
href="https://www.google.com"
rel="noreferrer noopener"
rel="noopener"
target="_blank"
>
https://www.google.com
Expand Down
38 changes: 22 additions & 16 deletions frontend/src/components/__snapshots__/Router.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -10,102 +10,108 @@ exports[`Router initial render 1`] = `
<Route
exact={true}
key="0"
path="/archive"
path="/start"
render={[Function]}
/>
<Route
exact={true}
key="1"
path="/artifacts"
path="/archive"
render={[Function]}
/>
<Route
exact={true}
key="2"
path="/artifact_types/:artifactType+/artifacts/:id"
path="/artifacts"
render={[Function]}
/>
<Route
exact={true}
key="3"
path="/executions"
path="/artifact_types/:artifactType+/artifacts/:id"
render={[Function]}
/>
<Route
exact={true}
key="4"
path="/execution_types/:executionType+/executions/:id"
path="/executions"
render={[Function]}
/>
<Route
exact={true}
key="5"
path="/experiments"
path="/execution_types/:executionType+/executions/:id"
render={[Function]}
/>
<Route
exact={true}
key="6"
path="/experiments/details/:eid"
path="/experiments"
render={[Function]}
/>
<Route
exact={true}
key="7"
path="/experiments/new"
path="/experiments/details/:eid"
render={[Function]}
/>
<Route
exact={true}
key="8"
path="/pipeline_versions/new"
path="/experiments/new"
render={[Function]}
/>
<Route
exact={true}
key="9"
path="/runs/new"
path="/pipeline_versions/new"
render={[Function]}
/>
<Route
exact={true}
key="10"
path="/pipelines"
path="/runs/new"
render={[Function]}
/>
<Route
exact={true}
key="11"
path="/pipelines/details/:pid/version/:vid?"
path="/pipelines"
render={[Function]}
/>
<Route
exact={true}
key="12"
path="/pipelines/details/:pid?"
path="/pipelines/details/:pid/version/:vid?"
render={[Function]}
/>
<Route
exact={true}
key="13"
path="/runs"
path="/pipelines/details/:pid?"
render={[Function]}
/>
<Route
exact={true}
key="14"
path="/recurringrun/details/:rid"
path="/runs"
render={[Function]}
/>
<Route
exact={true}
key="15"
path="/runs/details/:rid"
path="/recurringrun/details/:rid"
render={[Function]}
/>
<Route
exact={true}
key="16"
path="/runs/details/:rid"
render={[Function]}
/>
<Route
exact={true}
key="17"
path="/compare"
render={[Function]}
/>
Expand Down
11 changes: 9 additions & 2 deletions frontend/src/lib/Flags.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
export enum Deployments {
KUBEFLOW = 'KUBEFLOW',
MARKETPLACE = 'MARKETPLACE',
}

export const KFP_FLAGS = {
DEPLOYMENT:
// tslint:disable-next-line:no-string-literal
window && window['KFP_FLAGS'] && window['KFP_FLAGS']['DEPLOYMENT'] === Deployments.KUBEFLOW
? Deployments.KUBEFLOW
window && window['KFP_FLAGS']
? // tslint:disable-next-line:no-string-literal
window['KFP_FLAGS']['DEPLOYMENT'] === Deployments.KUBEFLOW
? Deployments.KUBEFLOW
: // tslint:disable-next-line:no-string-literal
window['KFP_FLAGS']['DEPLOYMENT'] === Deployments.MARKETPLACE
? Deployments.MARKETPLACE
: undefined
: undefined,
};
Loading