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] Switch Canvas to use React Router #100579

Merged
merged 13 commits into from
Jun 1, 2021

Conversation

crob611
Copy link
Contributor

@crob611 crob611 commented May 25, 2021

Summary

Closes #99815
Fixes #94575

This pull request switches Canvas to use React Router for its routing needs, and all that comes along with that.

Some key changes worth mentioning

  1. We have some state in the app that needs to be reflected in the URL (isFullscreen, etc), but the source of truth of that has previously been in redux. So it's always been tricky to keep those two places N'Sync.

Now, the url will always be the source of truth and we don't even sync that data to redux, opting instead to pass any kind of information or functionality related to routing around as a Context.

  1. Autoplay was a little strange because internally we had two pieces of state, autoplayEnabled and autoplayInterval. So you would have to set the interval and then specifically have to choose autoplay to be on. This is different than how autoRefresh works, where you would just select the refreshInterval and then it would be on. I changed this so that the two match now. Choosing an interval for autoplay automatically turns it on and the url will be updated to match the selected interval.

The view menu without "Stop/Start Autoplay"
image

Autoplay menu now has an X to disable autoplay, same as auto refresh
image

There is also a keyboard shortcut for disable autoplay. This would turn autoplay off and the url would be updated so there was no autoplay in it. I changed this slightly so that the keyboard shortcut internally pauses the autoplay, but nothing will be reflected in the url.

  1. This kills A LOT of our redux middleware and most of it is just replaced by pretty simple hooks at the top level of the workpad component. I think it simplifies things a lot.

Testing

This touches a lot, so testing as much as possible is great. Anything that involves routing is going to be the most likely to be impacted, so I'll call out some of the important things
[ ] Undo/Redo on a workpad with Keyboard Shortcuts, Edit Menu links, and browser forward/back navigation
[ ] Changes to workpads that result in a change to the page number you are on. (adding a page, deleting a page, moving a page, etc)
[ ] Creating empty workpads and creating workpads from templates
[ ] Export

@crob611 crob611 added review Team:Presentation Presentation Team for Dashboard, Input Controls, and Canvas loe:x-large Extra Large Level of Effort v8.0.0 release_note:skip Skip the PR/issue when compiling release notes impact:high Addressing this issue will have a high level of impact on the quality/strength of our product. Feature:Canvas v7.14.0 labels May 25, 2021
@crob611 crob611 requested review from a team as code owners May 25, 2021 17:59
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-presentation (Team:Presentation)

Copy link
Contributor

@ryankeairns ryankeairns left a comment

Choose a reason for hiding this comment

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

Approving the SCSS changes and noting that they're unrelated to the form layout issue. I'm not sure when that was broken, but the button and input are misaligned in that screenshot.

@crob611
Copy link
Contributor Author

crob611 commented May 25, 2021

@ryankeairns yes thanks for pointing that out. I used the same layout as the AutorefreshControls, which is broken. I thought it might have just been Amsterdam related but it's broken on v7 theme as well. I'll make an issue to follow up on that.

Copy link
Contributor

@clintandrewhall clintandrewhall left a comment

Choose a reason for hiding this comment

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

Epic work, @crob611 ... some stuff I've mentioned I might leave to a follow-up, but just a stellar job. Let's get it in so we can iterate and avoid tie-ups in CI.

@@ -178,7 +170,4 @@ export const teardownCanvas = (coreStart: CoreStart, startPlugins: CanvasStartDe

coreStart.chrome.setBadge(undefined);
coreStart.chrome.setHelpExtension(undefined);

destroyHistory();
stopRouter();
};
Copy link
Contributor

Choose a reason for hiding this comment

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

This whole file makes me happy... and it's the first code file I'm reviewing. 🚀

import PropTypes from 'prop-types';
import { History } from 'history';
// @ts-expect-error
import createHashStateHistory from 'history-extra/dist/createHashStateHistory';
Copy link
Contributor

Choose a reason for hiding this comment

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

Um... we should replace this soon, too.

https://www.npmjs.com/package/history-extra

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep. I left this alone because we will have to switch from Hash routing because the HashHistory that comes from the history package does not allow pushState, which is what the history-extra package allows. It should be a fairly straightforward switch, or we wait for the next version of history which I believe is going to allow state on the hash.

import { shortcutManager } from '../../lib/shortcut_manager';
import { CanvasRouter } from '../../routes';

class ShortcutManagerContextWrapper extends React.Component {
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be refactored soon, too.

https://reactjs.org/docs/legacy-context.html

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, the ReactShortcuts package we use uses the legacy context, hence the need for it here. That package is also not really maintained, so may want to look into other replacements that are more up to date.

import { EuiPanel, EuiLoadingChart, EuiSpacer, EuiText } from '@elastic/eui';

export const CanvasLoading = ({ msg }) => (
export const CanvasLoading: FC<{ msg?: string }> = ({ msg = 'Loading...' }) => (
Copy link
Contributor

Choose a reason for hiding this comment

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

i18n?

<Link name="loadWorkpad" params={{ id }}>
Edit Workpad
</Link>
<RoutingLink to={`/workpad/${id}`}>Edit Workpad</RoutingLink>
Copy link
Contributor

Choose a reason for hiding this comment

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

i18n?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is on the PDF export page, so I don't think it really needs i18n since it's never actually going to be seen. Not sure why that link is even there really.

removeWorkpads={removeWorkpads}
onClose={onClose}
workpads={workpadsState}
formatDate={formatDate}
Copy link
Contributor

Choose a reason for hiding this comment

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

This is easier as:

const { workpadId, canUserWrite } = fromState;
<Component
  downloadWorkpad={onDownloadWorkpad}
  workpads={workpadsState}
  {...{
    workpadId,
    canUserWrite,
    cloneWorkpad,
    createWorkpad,
    findWorkpads,
    removeWorkpads, 
	onClose,
	formatDate,
  }}
/>

I'd love to see consistency in event handlers, (e.g. downloadWorkpad becomes onDownloadWorkpad, createWorkpad becomes onCreateWorkpad, etc)

const { setFullscreen } = services.platform;

useEffect(() => {
const body = document.querySelector('body');
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't this just document.body with the potential of being undefined?

}

useEffect(() => {
if (pageIndex !== workpad.page) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should consider removing the param from the url if malformed. (follow-up)

path={'/workpad/:id'}
exact={false}
children={(route: WorkpadRouteProps) => {
return [
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: can just return the array.

/>
);

export const ExportRouteManager: FC = ({ children }) => {
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 almost like to see this split out into individual files.

@crob611
Copy link
Contributor Author

crob611 commented May 28, 2021

@elasticmachine merge upstream

@kibanamachine
Copy link
Contributor

merge conflict between base and head

@crob611
Copy link
Contributor Author

crob611 commented May 28, 2021

@elasticmachine merge upstream


const pageNumber = parseInt(params.pageNumber, 10);
let pageIndex = workpad.page;
if (!isNaN(pageNumber)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

The comment below was actually for ^this line.

We should consider removing the param from the url if malformed. (follow-up)

@crob611
Copy link
Contributor Author

crob611 commented Jun 1, 2021

@elasticmachine merge upstream

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
canvas 1100 1090 -10

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
canvas 1.3MB 1.3MB -22.8KB

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
canvas 534.1KB 534.7KB +575.0B
Unknown metric groups

References to deprecated APIs

id before after diff
canvas 29 25 -4
crossClusterReplication 8 6 -2
fleet 22 20 -2
globalSearch 4 2 -2
indexManagement 12 7 -5
infra 261 149 -112
lens 67 45 -22
licensing 18 15 -3
lists 239 236 -3
maps 286 208 -78
ml 121 115 -6
monitoring 109 56 -53
securitySolution 390 346 -44
stackAlerts 101 95 -6
total -342

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

Copy link
Contributor

@poffdeluxe poffdeluxe left a comment

Choose a reason for hiding this comment

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

Approving to unblock! Tested workpads with embeddables and generated lots of PDFs!

Only issue I found was the "undo after fullscreen" issue

@crob611 crob611 added the auto-backport Deprecated - use backport:version if exact versions are needed label Jun 1, 2021
@crob611 crob611 merged commit b62848c into elastic:master Jun 1, 2021
kibanamachine added a commit to kibanamachine/kibana that referenced this pull request Jun 1, 2021
* Switch Canvas to use React Router

* Fix typescript errors

* Remove @scant/router from package.json

* Fix tests

* Fix functional test

* Fix functional tests

* Fix bad merge in package.json

* Cleanup from code review comments

* Fix double basepath append

Co-authored-by: Kibana Machine <[email protected]>
@kibanamachine
Copy link
Contributor

💚 Backport successful

Status Branch Result
7.x

This backport PR will be merged automatically after passing CI.

@clintandrewhall
Copy link
Contributor

Thank you @crob611 and @poffdeluxe !!

jloleysens added a commit to jloleysens/kibana that referenced this pull request Jun 2, 2021
…sens/kibana into reporting/new-png-pdf-report-type

* 'reporting/new-png-pdf-report-type' of github.com:jloleysens/kibana: (46 commits)
  [Security Solution] Add Ransomware canary advanced policy option (elastic#101068)
  [Exploratory view] Core web vitals (elastic#100320)
  [Security solution][Endpoint] Add unit tests for fleet event filters/trusted apps cards (elastic#101034)
  [Lens] Use a setter function for the dimension panel (elastic#101123)
  [Index Patterns] Fix return saved index pattern object (elastic#101051)
  [CI] For PRs, build TS refs before public api docs check (elastic#100791)
  [Maps] fix line and polygon label regression (elastic#101085)
  Migrate CCR to new ES JS client. (elastic#100131)
  [Canvas] Switch Canvas to use React Router (elastic#100579)
  [Expressions] Use table column ID instead of name when set (elastic#99724)
  [DOCS] Updates docs landing page (elastic#100749)
  [DOCS] Corrects typo in step 3 (elastic#101079)
  [DOCS] Updates runtime example in Discover (elastic#100926)
  Migrate kibana.autocomplete config to data plugin (elastic#100586)
  [Uptime] New width/delay definition for waterfall sidebar item tooltip (elastic#100147)
  [FTR] Use importExport for saved_object/basic archive (elastic#100244)
  [Fleet] Better input for multi text input in agent policy builder (elastic#101020)
  [CI] Buildkite support with Baseline pipeline (elastic#100492)
  [Reporting/Telemetry] Do not send telemetry if we are in screenshot mode (elastic#100388)
  Create API keys with metadata (elastic#100682)
  ...
@kibanamachine kibanamachine added the backport missing Added to PRs automatically when the are determined to be missing a backport. label Jun 3, 2021
@kibanamachine
Copy link
Contributor

Looks like this PR has a backport PR but it still hasn't been merged. Please merge it ASAP to keep the branches relatively in sync.

2 similar comments
@kibanamachine
Copy link
Contributor

Looks like this PR has a backport PR but it still hasn't been merged. Please merge it ASAP to keep the branches relatively in sync.

@kibanamachine
Copy link
Contributor

Looks like this PR has a backport PR but it still hasn't been merged. Please merge it ASAP to keep the branches relatively in sync.

crob611 pushed a commit to crob611/kibana that referenced this pull request Jun 8, 2021
* Switch Canvas to use React Router

* Fix typescript errors

* Remove @scant/router from package.json

* Fix tests

* Fix functional test

* Fix functional tests

* Fix bad merge in package.json

* Cleanup from code review comments

* Fix double basepath append

Co-authored-by: Kibana Machine <[email protected]>
# Conflicts:
#	package.json
crob611 pushed a commit that referenced this pull request Jun 8, 2021
* Switch Canvas to use React Router

* Fix typescript errors

* Remove @scant/router from package.json

* Fix tests

* Fix functional test

* Fix functional tests

* Fix bad merge in package.json

* Cleanup from code review comments

* Fix double basepath append

Co-authored-by: Kibana Machine <[email protected]>
# Conflicts:
#	package.json
@kibanamachine
Copy link
Contributor

Looks like this PR has backport PRs but they still haven't been merged. Please merge them ASAP to keep the branches relatively in sync.

@kibanamachine kibanamachine removed the backport missing Added to PRs automatically when the are determined to be missing a backport. label Jun 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auto-backport Deprecated - use backport:version if exact versions are needed Feature:Canvas impact:high Addressing this issue will have a high level of impact on the quality/strength of our product. loe:x-large Extra Large Level of Effort release_note:skip Skip the PR/issue when compiling release notes review Team:Presentation Presentation Team for Dashboard, Input Controls, and Canvas v7.14.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Canvas] Migrate to React Router Canvas workpads copied to other spaces with random ids cannot be opened
6 participants