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

[Portable Dashboards] Remove Saved Object Class #138774

Merged

Conversation

ThomThomson
Copy link
Contributor

@ThomThomson ThomThomson commented Aug 12, 2022

Summary

Fixes #137200
Fixes #136767

This PR executes a number of large changes to the way that Dashboards are loaded from Saved Objects. This is required as preparation for the first phase of the Portable Dashboards project. Merging this PR will complete all remaining prep work items and allow us to move on to implementation.

What does this PR do?

  • Removes the Dashboard Saved Object Class as well as the Saved Dashboard Loader, as well the implementation of the generic Saved Object Loader which was moved into the Dashboard plugin in Move saved objects loader to dashboard plugin #124708 because we were the only consumer. @elastic/ml-ui the codeowners review requirement is only due to a type change.
  • Introduces a new Dashboard Saved Object Service using the services abstraction to load, find, and save Dashboard saved objects. Finishes up some small todos left from [Dashboard] Services abstraction #139145 by removing all instances of useKibana, and dashboardAppState.
  • Removes clientside migrations Fixes [Portable Dashboards] Remove Legacy Clientside Migrations  #137200 by removing all of the client side migration code that runs on every dashboard startup. Instead, any dashboard panels from before 7.3 will not be loaded into the dashboard state, and a warning toast will show. The functional tests have also been updated to expect this toast.
  • Reorganizes legacy saved object migrations Places all of the types and migrations related to Dashboard saved object migrations from before 7.3 into their own folder, simplifying the readability of the dashboard migration code. The migrations have no changes.
  • Standardizes Dashboard Attributes Typing by adding a new type DashboardAttributes which should be always be the latest / current state of the Dashboard Saved Object Attributes. Rather than keeping version information in this type, we should create new types to store the previous versions, maintaining DashboardAttributes as the source of truth for the latest typings.
  • Deletes dead code including an entire persistable state system implementation and
    the unused url library function.
  • Imports all actions async in order to reduce bundle size, and allow the whole services implementation to be loaded as an async chunk, all dashboard actions are now registered and imported asynchronously.
  • Adds a few functional test lib functions because dashboard security and spaces tests were using the common object for navigation which made the tests liable to break with the code changes. I introduced functions on the dashboard page object to handle these navigations.

Test Guide

Saving and loading

Make sure to manually save in as many ways as possible:

  • Quick save
  • Save as copy
  • Save as, with rename
  • Save as, change tags
  • Save as change description
  • Clone dashboard

Everything should work correctly

Migrations

Export a dashboard from a version before 7.3 and import it into main. All of the saved object migrations should run correctly.
Edit: It looks like versioning must go through 7.17.x before being upgraded to 8.x, for both upgrades and saved object imports. So we should be okay just ensuring that imports from 7.17.x work correctly.

Saved Object Resolve

To test the conflict, exactMatch, and aliasMatch outcomes of the savedObjectsClient.resolve function, the results of which are used slightly differently in this PR you should:

  1. Run this PR locally and log in as the system_indices_superuser
  2. Install sample flights data
  3. Load the resolve-staging-data.txt via dev tools
  4. Make the flights data view available in all spaces through the Saved Objects management screen
  5. Navigate to {your Kibana URL}/s/test1/app/dashboards#/view/b348e380-39d1-11ed-88ea-15ffd58ee0d7-test1 and ensure that the dashboard loads properly.
  6. Navigate to {your Kibana URL}/s/test2/app/dashboards#/view/b348e380-39d1-11ed-88ea-15ffd58ee0d7-test2 and you should be redirected to another dashboard with the id b348e380-39d1-11ed-88ea-15ffd58ee0d7-newId
  7. Navigate to {your Kibana URL}/s/test3/app/dashboards#/view/b348e380-39d1-11ed-88ea-15ffd58ee0d7-test3 and the conflict warning should show.

/**
* A saved dashboard panel parsed directly from the Dashboard Attributes panels JSON
*/
export type SavedDashboardPanel = SerializableRecord & {
Copy link
Contributor

@rudolf rudolf Sep 5, 2022

Choose a reason for hiding this comment

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

While on the surface having a type that guarantees that data is serialisable is a good thing, we should be very careful with the SerializableRecord or Serializable types. These are really anti-types in that they reduce type safety making code more prone to bugs.

As an example mySavedDashboardPanel.recordDoesNotExist.fieldDoesNotExist = 'some string' would happily pass the type checker. So it really has the same problems as using any.

I know this PR didn't introduce this type to the dashboard code, but if we could limit/reduce it's usage that would improve the quality of the code.

Copy link
Contributor

Choose a reason for hiding this comment

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

I realised this problem is much bigger and we also have the SavedObjectAttributes type causing similar problems 🙈 https://github.com/elastic/kibana/pull/140099/files

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey @rudolf, this is a really good point! Let me look into removing any instances of SerializableRecord from Dashboard. I wonder if there are any Typescript extension types that we can use to enforce serializability without introducing that nasty key signature.

Copy link
Contributor Author

@ThomThomson ThomThomson Sep 19, 2022

Choose a reason for hiding this comment

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

I've removed a couple references to SerializableRecord here, but removing all of the SavedObjectAttributes imports from Dashboard is proving to be a big enough project to warrant its own follow-up PR. I have created this issue to track it

@Heenawter Heenawter mentioned this pull request Sep 8, 2022
3 tasks
ThomThomson and others added 23 commits September 8, 2022 20:25
@ThomThomson ThomThomson marked this pull request as ready for review September 23, 2022 17:25
@ThomThomson ThomThomson requested review from a team as code owners September 23, 2022 17:25
@elasticmachine
Copy link
Contributor

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

@Heenawter Heenawter self-requested a review September 23, 2022 17:26
Comment on lines +45 to +50
screenshotMode: { isScreenshotMode },
coreContext: { executionContext },
data: { search },
embeddable: { getStateTransfer },
notifications: { toasts },
screenshotMode: { isScreenshotMode },
settings: { uiSettings },
spaces: { getLegacyUrlConflict },
data: { search },
Copy link
Contributor

Choose a reason for hiding this comment

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

Very minor nit: I was trying to keep the services alphabetical when I did the abstraction, but I notice here you're ordering by the number of characters in the line - not sure if we want to be consistent about this? 🤷

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I always organize imports and de-structuring by number of characters to make the file look pretty ✨. The way I do it is definitely not something we should standardize in my opinion hahah. So that leaves two options here:

Option 1: We make alphabetical imports / de-structuring our team's standard, and we look into making a prettier / eslint rule to automatically do that for us.

Option 2: We leave it totally up to the engineer who is editing the file.

I'm totally okay with either option! @cqliu1, this is something the 3 of us should probably think about.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm also good with either! Definitely something worth discussing so we can all get on the same page, since I know it's come up a few times at this point 👍

src/plugins/dashboard/public/dashboard_strings.ts Outdated Show resolved Hide resolved
src/plugins/dashboard/public/dashboard_strings.ts Outdated Show resolved Hide resolved
src/plugins/dashboard/public/plugin.tsx Show resolved Hide resolved
Copy link
Contributor

@Heenawter Heenawter left a comment

Choose a reason for hiding this comment

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

Code review only - looks like this realllly helps clean things up! Left a few nits and questions, but nothing code-specific stood out to me 👍

Will follow up with approval once I test this locally

Copy link
Contributor

@Heenawter Heenawter left a comment

Choose a reason for hiding this comment

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

Working on testing this PR as thoroughly as possible, and was able to get stuck in an unsaved changes state via the following steps:

  1. Create a new dashboard and save it with Store time with dashboard off
  2. Click Save as, untick Save as new, set Store time with dashboard to true
  3. Change the dashboard time range - notice that this does not trigger unsaved changes, even though it should 🔥
  4. Go back to Save as, untick Save as new but keep Store time with dashboard as true
  5. Notice you get stuck in unsaved changes and can't get out even if you discard changes 🔥
Screen.Recording.2022-09-23.at.2.54.43.PM.mov

If in step one you save the brand new dashboard with Store time with dashboard on in the first place, the unsaved changes badge seems to respond to time changes as expected - it's only when you go from Store time with dashboard off to on where things get buggy,

Copy link
Contributor

@Heenawter Heenawter left a comment

Choose a reason for hiding this comment

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

Tested this and everything worked great minus the bug discussed in #138774 (review). Will approve once that is resolved so I can do another round of testing.

Saving and loading

For an empty dashboard and for dashboards with content:

  • Quick save:
    • Added and modified controls, renamed panels, moved them around, etc. etc. Everything worked as expected
  • Save as:
    • Saved dashboard with title, description, tags, and time store
    • Made sure I could make changes to title, description, tags, and time store by unchecking Save as new dashboard when saving
    • Get a warning when trying to Save as with duplicated title - can overwrite it
  • Clone dashboard:
    • Cloned the dashboard and ensured everything got copied as expected, including by reference and by value visualizations (if the dashboard wasn't empty), tags, description, and time store
    • Get a warning when trying to clone with duplicated title - can overwrite it

Migrations

  • Took a dashboard with content from 7.17.3 and imported it
  • Took an empty dashboard from 7.17.3 and imported it

Saved Object Resolve

Followed the steps outlined and everything worked as expected 👍

Copy link
Contributor

@darnautov darnautov left a comment

Choose a reason for hiding this comment

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

ML changes LGTM

@ThomThomson
Copy link
Contributor Author

@Heenawter - I was able to fix the bug you described in #138774 (review). Nice catch! It was basically a matter of correctly applying all of the state from the save modal. I also cleaned up the state comparison of times a little bit to make it match with the rest of the state comparison.

Copy link
Contributor

@Heenawter Heenawter left a comment

Choose a reason for hiding this comment

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

Reviewed code changes + re-tested the timeRestore bug and everything works great 🎉 Also tried the following and everything worked beautifully:

  1. Save a new dashboard with timeRestore === true
  2. Change the time and verify that unsaved changes badge shows up
  3. Click Save as, untick both Store time with dashboard and Save as new dashboard, then confirm
  4. The unsaved changes badge disappears as expected 👍

@ThomThomson
Copy link
Contributor Author

@elasticmachine merge upstream

@jbudz
Copy link
Member

jbudz commented Sep 27, 2022

buildkite test this

@ThomThomson ThomThomson force-pushed the portableDashboard/removeSavedObjectClass branch from 61452ce to 1d93a4d Compare September 27, 2022 23:42
@ThomThomson
Copy link
Contributor Author

@elasticmachine merge upstream

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
dashboard 395 385 -10

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
dashboard 139 113 -26

Async chunks

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

id before after diff
dashboard 388.1KB 418.2KB +30.1KB

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
dashboard 10 3 -7

Page load bundle

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

id before after diff
dashboard 72.2KB 41.0KB -31.2KB
Unknown metric groups

API count

id before after diff
dashboard 144 120 -24

async chunk count

id before after diff
dashboard 5 8 +3

ESLint disabled line counts

id before after diff
dashboard 8 7 -1

References to deprecated APIs

id before after diff
dashboard 60 56 -4

Total ESLint disabled count

id before after diff
dashboard 8 7 -1

Unreferenced deprecated APIs

id before after diff
savedObjects 1 2 +1

History

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting Feature:Dashboard Dashboard related features 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 Project:Portable Dashboard Related to the Portable Dashboards initiative release_note:skip Skip the PR/issue when compiling release notes Team:Presentation Presentation Team for Dashboard, Input Controls, and Canvas v8.6.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Portable Dashboards] Remove Legacy Clientside Migrations [Portable Dashboards] Remove Saved Object Class
8 participants