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

[Canvas] Move Templates to be stored as Saved Objects #69438

Merged
merged 7 commits into from
Jun 30, 2020
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 0 additions & 2 deletions x-pack/plugins/canvas/canvas_plugin_src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import { initializeViews } from './uis/views';
// @ts-ignore Untyped Local
import { initializeArgs } from './uis/arguments';
import { tagSpecs } from './uis/tags';
import { templateSpecs } from './templates';

interface SetupDeps {
canvas: CanvasSetup;
Expand Down Expand Up @@ -60,7 +59,6 @@ export class CanvasSrcPlugin implements Plugin<void, void, SetupDeps, StartDeps>
plugins.canvas.addViewUIs(initializeViews(core, plugins));
plugins.canvas.addArgumentUIs(initializeArgs(core, plugins));
plugins.canvas.addTagUIs(tagSpecs);
plugins.canvas.addTemplates(templateSpecs);
plugins.canvas.addTransformUIs(transformSpecs);
}

Expand Down
21 changes: 0 additions & 21 deletions x-pack/plugins/canvas/canvas_plugin_src/templates/index.ts

This file was deleted.

816 changes: 0 additions & 816 deletions x-pack/plugins/canvas/canvas_plugin_src/templates/status_report.json

This file was deleted.

455 changes: 0 additions & 455 deletions x-pack/plugins/canvas/canvas_plugin_src/templates/summary_report.json

This file was deleted.

335 changes: 0 additions & 335 deletions x-pack/plugins/canvas/canvas_plugin_src/templates/theme_dark.json

This file was deleted.

342 changes: 0 additions & 342 deletions x-pack/plugins/canvas/canvas_plugin_src/templates/theme_light.json

This file was deleted.

2 changes: 2 additions & 0 deletions x-pack/plugins/canvas/common/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { SHAREABLE_RUNTIME_NAME } from '../../shareable_runtime/constants_static

export const CANVAS_TYPE = 'canvas-workpad';
export const CUSTOM_ELEMENT_TYPE = 'canvas-element';
export const TEMPLATE_TYPE = `${CANVAS_TYPE}-template`;
export const CANVAS_APP = 'canvas';
export const APP_ROUTE = '/app/canvas';
export const APP_ROUTE_WORKPAD = `${APP_ROUTE}#/workpad`;
Expand All @@ -16,6 +17,7 @@ export const API_ROUTE_WORKPAD = `${API_ROUTE}/workpad`;
export const API_ROUTE_WORKPAD_ASSETS = `${API_ROUTE}/workpad-assets`;
export const API_ROUTE_WORKPAD_STRUCTURES = `${API_ROUTE}/workpad-structures`;
export const API_ROUTE_CUSTOM_ELEMENT = `${API_ROUTE}/custom-element`;
export const API_ROUTE_TEMPLATES = `${API_ROUTE}/templates`;
export const LOCALSTORAGE_PREFIX = `kibana.canvas`;
export const LOCALSTORAGE_CLIPBOARD = `${LOCALSTORAGE_PREFIX}.clipboard`;
export const SESSIONSTORAGE_LASTPATH = 'lastPath:canvas';
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/canvas/i18n/templates/apply_strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ export const applyTemplateStrings = (templates: CanvasTemplate[]) => {
});
}

return () => template;
return template;
});
};
8 changes: 4 additions & 4 deletions x-pack/plugins/canvas/i18n/templates/template_strings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
*/

import { getTemplateStrings } from './template_strings';
import { templateSpecs } from '../../canvas_plugin_src/templates';
import { templates } from '../../server/templates'; // eslint-disable-line

import { TagStrings } from '../tags';

describe('TemplateStrings', () => {
const templateStrings = getTemplateStrings();
const templateNames = templateSpecs.map((template) => template().name);
const templateNames = templates.map((template) => template.name);
const stringKeys = Object.keys(templateStrings);

test('All template names should exist in the strings definition', () => {
Expand Down Expand Up @@ -39,8 +39,8 @@ describe('TemplateStrings', () => {
test('All templates should have tags that are defined', () => {
const tagNames = Object.keys(TagStrings);

templateSpecs.forEach((template) => {
template().tags.forEach((tagName: string) => expect(tagNames).toContain(tagName));
templates.forEach((template) => {
template.tags.forEach((tagName: string) => expect(tagNames).toContain(tagName));
});
});
});
3 changes: 0 additions & 3 deletions x-pack/plugins/canvas/i18n/templates/template_strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,6 @@ export const getTemplateStrings = (): TemplateStringDict => ({
defaultMessage: 'Infographic-style report with live charts',
}),
},
});

export const getUnusedTemplateStrings = (): TemplateStringDict => ({
Pitch: {
name: i18n.translate('xpack.canvas.templates.pitchName', {
defaultMessage: 'Pitch',
Expand Down
57 changes: 0 additions & 57 deletions x-pack/plugins/canvas/public/components/paginate/index.js

This file was deleted.

87 changes: 87 additions & 0 deletions x-pack/plugins/canvas/public/components/paginate/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import { Paginate as Component } from './paginate';

interface InPaginateProps {
perPage?: number;
startPage?: number;
rows: any[];
children: (props: PaginateChildProps) => React.ReactNode;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd consider changing this to childFn... I was confused about this being a function producing children as opposed to a collection of children.

}

export type PaginateProps = Omit<InPaginateProps, 'startPage'> & {
pageNumber: number;
totalPages: number;
nextPageEnabled: boolean;
prevPageEnabled: boolean;
setPage: (num: number) => void;
nextPage: () => void;
prevPage: () => void;
};

export type PaginateChildProps = Omit<PaginateProps, 'children'>;

export const Paginate: React.FunctionComponent<InPaginateProps> = ({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you can import FC in the import statement above and shorten this line considerably.

perPage = 10,
startPage = 0,
rows,
children,
}) => {
const totalPages = Math.ceil(rows.length / perPage);
const initialCurrentPage = totalPages > 0 ? Math.min(startPage, totalPages - 1) : 0;
const [currentPage, setPage] = useState(initialCurrentPage);
const hasRenderedRef = useRef<boolean>(false);
const maxPage = totalPages - 1;
const start = currentPage * perPage;
const end = currentPage === 0 ? perPage : perPage * (currentPage + 1);
const nextPageEnabled = currentPage < maxPage;
const prevPageEnabled = currentPage > 0;
const partialRows = rows.slice(start, end);

const nextPage = () => {
if (nextPageEnabled) {
setPage(currentPage + 1);
}
};

const prevPage = () => {
if (prevPageEnabled) {
setPage(currentPage - 1);
}
};

useEffect(() => {
if (!hasRenderedRef.current) {
hasRenderedRef.current = true;
} else {
setPage(0);
}
}, [perPage, hasRenderedRef]);

return (
<Component
rows={partialRows}
perPage={perPage}
pageNumber={currentPage}
totalPages={totalPages}
setPage={setPage}
nextPage={nextPage}
prevPage={prevPage}
nextPageEnabled={nextPageEnabled}
prevPageEnabled={prevPageEnabled}
children={children}
/>
);
};

Paginate.propTypes = {
rows: PropTypes.array.isRequired,
perPage: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
startPage: PropTypes.number,
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,31 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import PropTypes from 'prop-types';
import { PaginateProps } from './';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I would put this props interface in this file and export the other direction... I've never liked how Redux expects the opposite. YMMV.


export const Paginate = (props) => {
return props.children({
rows: props.partialRows,
perPage: props.perPage,
pageNumber: props.pageNumber,
totalPages: props.totalPages,
nextPageEnabled: props.nextPageEnabled,
prevPageEnabled: props.prevPageEnabled,
setPage: (num) => props.setPage(num),
nextPage: props.nextPage,
prevPage: props.prevPage,
});
export const Paginate: React.FunctionComponent<PaginateProps> = (props) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: destructure this object so you can avoid the props. in the object below.

return (
<React.Fragment>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you can use <> and </>

{props.children({
rows: props.rows,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: doesn't this collection match props...? You might consider:


export const Paginate: FC<PaginateProps> = (props) => (
  <>{children(props)}</>
);

...or...

export const Paginate: FC<PaginateProps> = ({ 
  perPage, 
  pageNumber, 
  totalPages, 
  nexPageEnabled, 
  prevPageEnabled, 
  setPage, 
  nextPage, 
  prevPage, 
  ...rest,
}) => (
  <>
    {props.children({
      perPage, 
      pageNumber, 
      totalPages, 
      nexPageEnabled, 
      prevPageEnabled, 
      setPage, 
      nextPage, 
      prevPage,
    })}
  </>
);

perPage: props.perPage,
pageNumber: props.pageNumber,
totalPages: props.totalPages,
nextPageEnabled: props.nextPageEnabled,
prevPageEnabled: props.prevPageEnabled,
setPage: props.setPage,
nextPage: props.nextPage,
prevPage: props.prevPage,
})}
</React.Fragment>
);
};

Paginate.propTypes = {
children: PropTypes.func.isRequired,
partialRows: PropTypes.array.isRequired,
rows: PropTypes.array.isRequired,
perPage: PropTypes.number.isRequired,
pageNumber: PropTypes.number.isRequired,
totalPages: PropTypes.number.isRequired,
Expand Down
19 changes: 19 additions & 0 deletions x-pack/plugins/canvas/public/components/router/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';

// TODO: We should fully build out this interface for our router
// or switch to a different router that is already typed
interface Router {
navigateTo: (
name: string,
params: Record<string, number | string>,
state?: Record<string, string>
) => void;
}

export const RouterContext = React.createContext<Router | undefined>(undefined);
1 change: 1 addition & 0 deletions x-pack/plugins/canvas/public/components/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
// @ts-ignore untyped local
import { Router as Component } from './router';
import { State } from '../../../types';
export * from './context';

const mapDispatchToProps = {
enableAutoplay,
Expand Down
7 changes: 6 additions & 1 deletion x-pack/plugins/canvas/public/components/router/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { routerProvider } from '../../lib/router_provider';
import { getAppState } from '../../lib/app_state';
import { getTimeInterval } from '../../lib/time_interval';
import { CanvasLoading } from './canvas_loading';
import { RouterContext } from './';

export class Router extends React.PureComponent {
static propTypes = {
Expand Down Expand Up @@ -97,6 +98,10 @@ export class Router extends React.PureComponent {
return React.createElement(CanvasLoading, { msg: this.props.loadingMessage });
}

return <this.state.activeComponent />;
return (
<RouterContext.Provider value={this.state.router}>
<this.state.activeComponent />
</RouterContext.Provider>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { WorkpadTemplates } from '../workpad_templates';
import { CanvasTemplate } from '../../../../types';

const templates: Record<string, CanvasTemplate> = {
test1: {
id: 'test1-id',
name: 'test1',
help: 'This is a test template',
tags: ['tag1', 'tag2'],
template_key: 'test1-key',
},
test2: {
id: 'test2-id',
name: 'test2',
help: 'This is a second test template',
tags: ['tag2', 'tag3'],
template_key: 'test2-key',
},
};

storiesOf('components/WorkpadTemplates', module)
.addDecorator((story) => <div style={{ width: '500px' }}>{story()}</div>)
.add('default', () => {
const onCreateFromTemplateAction = action('onCreateFromTemplate');
return (
<WorkpadTemplates
templates={templates}
onClose={action('onClose')}
onCreateFromTemplate={(template) => {
onCreateFromTemplateAction(template);
return Promise.resolve();
}}
/>
);
});
Loading