Skip to content

Spaces - Copy Saved Objects to Spaces UI#39002

Merged
legrego merged 50 commits intoelastic:masterfrom
legrego:copy-to-space-ui
Aug 23, 2019
Merged

Spaces - Copy Saved Objects to Spaces UI#39002
legrego merged 50 commits intoelastic:masterfrom
legrego:copy-to-space-ui

Conversation

@legrego
Copy link
Member

@legrego legrego commented Jun 14, 2019

Summary

This introduces a new "Copy to space" action within the Saved Objects Management UI. When Spaces is enabled, a new action appears in the table next to each saved object. From there, users are given the option to copy that saved object (with or without references) to one or more other spaces.

Tasks

  • create workflow
  • create integration points in saved objects management ui
  • integrate with actual APIs from Copy Saved Objects to Spaces API #38014
  • testing
  • i18n verification
  • a11y verification
  • copy review

cts_demo

Menu option

cts_1

Select spaces to copy into

cts_2

Processing copy

cts_3

Copy response, showing sample error

cts_4

Copy response, showing conflict resolution

cts_5

cts_6

Resolves #37286

"Release notes: Saved objects can be easily copied from one space to another from the Saved Objects Management screen"

@legrego
Copy link
Member Author

legrego commented Jun 14, 2019

@cchaos no rush, as the implementation is blocked on several other PRs, but if you get some free time, I'd love a preliminary design review!

@legrego legrego added Team:Security Platform Security: Auth, Users, Roles, Spaces, Audit Logging, etc t// Feature:Security/Spaces Platform Security - Spaces feature WIP Work in progress labels Jun 14, 2019
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-security

};
}

export abstract class SavedObjectsManagementAction<T = unknown> {
Copy link
Member Author

Choose a reason for hiding this comment

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

This is tightly coupled to both EUI and React. My ultimate goal is to replace this entirely with the Embeddable/Actions APIs once they're ready, so I don't want to spend a ton of time crafting the perfect abstraction here. Instead, this provides enough functionality to enable the copy-to-space feature, without coupling it to Spaces itself.

@elasticmachine
Copy link
Contributor

elasticmachine commented Jun 14, 2019

💔 Build Failed

^ Unrelated CI failure

@elasticmachine
Copy link
Contributor

💔 Build Failed

@elasticmachine
Copy link
Contributor

💔 Build Failed

@elasticmachine
Copy link
Contributor

💔 Build Failed

@Conky5
Copy link
Contributor

Conky5 commented Jul 8, 2019

retest

@elasticmachine
Copy link
Contributor

💔 Build Failed

@cchaos
Copy link
Contributor

cchaos commented Jul 15, 2019

@legrego Sorry it's taken so long for the design team to take a look at this. @ryankeairns will actually be able to help you out on it. You'll probably want to sync with him to go over the purpose and intricacies of all the Spaces stuffs.

@legrego
Copy link
Member Author

legrego commented Aug 1, 2019

@ryankeairns I updated the screenshots in this PR summary to reflect my changes based on your mockup. It's not production ready, but it hopefully gives you an idea of the direction I took.

I deviated from your mockup in a couple of places. I'm more than willing to make any adjustments you see fit:

  • Added "skip" option to undo the "overwrite" button click. Based on the mockup, there was no way to indicate that you no longer wanted to overwrite the saved object. This adds a "skip" option if you want to cancel this operation.
  • Added selected options to the top of the processing screen, which just reflects the chosen options (include related, automatically overwrite)
  • Added operation summary to the footer, showing number of copied, pending, skipped (due to conflict), and errors.

Since there is no way to automatically expand accordions (except on initial render), I wanted a way to surface the fact that something might need your attention, so I put that summary near the "Finish" button to hopefully make that a little clearer.

This also includes a couple of sass entries, which are probably worth looking at to make sure I'm not doing anything crazy.

Copy link
Contributor

@kobelb kobelb left a comment

Choose a reason for hiding this comment

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

Nice work, everything seems to be working well. My primary concern is with regard to the missing references functionality, and not being able to test it.

It's super pedantic, but I'm not the biggest fan of using the CTS acronym. It's used rather inconsistently... For the classes/interfaces which aren't exported outside of the x-pack/legacy/plugins/spaces/public/views/management/components/copy_saved_objects_to_space folder, perhaps we could just use "short names" and drop the "Copy to Space" part?

We also are re-using types and processImportResponse from the saved objects import, which is somewhat awkward. It isn't obvious that internally copy to space is relying upon import/export.

Also, when choosing to "overwrite" a saved object, should we change the test of the "Finish" button? It wasn't immediately obvious to me that clicking "overwrite" wasn't enough to actually overwrite it and that we were just marking it to be retried once we hit "Finish".

export {
processImportResponse,
ProcessedImportResponse,
} from '../../../../core_plugins/kibana/public/management/sections/objects/lib/process_import_response';
Copy link
Contributor

Choose a reason for hiding this comment

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

We shouldn't be reaching into the kibana plugin from here, should we move process_import_response to src/legacy/ui/public/management/saved_objects_management/?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, I thought this was acceptable because we do the same thing from src/legacy/ui/public/management/index.js today to share functionality between OSS and X-Pack

Copy link
Contributor

Choose a reason for hiding this comment

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

Interesting... well, let the "bad practices" roll :) Feel free to ignore this.


useEffect(() => {
setIsLoading(true);
kfetch({ pathname: '/api/spaces/space', query: { purpose } }).then((response: Space[]) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

We're using kfetch directly, should we be using the SpacesManager?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah ideally. Passing the SpacesManager into the hook would be problematic I think...it's awkward to pass it as a dependency of the hook, because then the hook really isn't doing anything important...it's just calling the SpacesManager for you.

I think I'll just remove this hook and replace it with a direct use of useEffect within the flyout to take advantage of the SpacesManager.

id: string;
name: string;
}
export interface SavedObjectRecord {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
export interface SavedObjectRecord {
export interface SavedObjectsManagementRecord {


import { ReactNode } from '@elastic/eui/node_modules/@types/react';

export interface SavedObjectReference {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
export interface SavedObjectReference {
export interface SavedObjectsManagementRecordReference {

export const SelectableSpacesControl = (props: Props) => {
const [options, setOptions] = useState<SpaceOption[]>([]);

useEffect(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we using this to compute the initial options for performance reasons? If doesn't seem like we're performing a true side effect here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good call, this was a holdover from an earlier experiment

props.savedObject,
spaceCopyResult,
props.copyOptions.includeRelated
) as SummarizedCopyToSpaceResult;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
) as SummarizedCopyToSpaceResult;
);

import { FormattedMessage } from '@kbn/i18n/react';
import {
summarizeCopyResult,
SummarizedCopyToSpaceResult,
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
SummarizedCopyToSpaceResult,

conflicts: conflicts.filter(
c => c.obj.type === savedObject.type && c.obj.id === savedObject.id
),
missingReferences,
Copy link
Contributor

Choose a reason for hiding this comment

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

Currently, if you try to use export or copy to space where a reference is missing, we get a 400 Bad Request is thrown. So, it's hard to tell how the missing references will actually be returned once this is fixed.

Do we really want all missing reference conflicts to show up here? Wouldn't this be all missing references for the entire "object graph" including transitive references?

For the direct references and transitive references, we end up listing all missing reference errors that are for the object itself. If that's correct, shouldn't the "missing reference" for the saved object we're trying to copy always be null/undefined?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, I think we're talking about different scenarios here. Any copy to space code that mentions "missing references" is talking about conditions which produce this import error:

export interface SavedObjectsImportMissingReferencesError {
type: 'missing_references';
references: Array<{
type: string;
id: string;
}>;
blocking: Array<{
type: string;
id: string;
}>;
}

Specifically, there are two conditions which cause this (that I'm aware of), both of which are produced by validate_references:

  • An object being imported directly depends on an index pattern which isn't provided in the upload/copy request, nor in the target space (e.g., unchecking "include references" when copying a visualization which references an index pattern into a fresh space)
  • An object being imported directly depends on a saved search which isn't provided in the upload/copy request, nor in the target space (e.g., unchecking "include references" when copying an index pattern which references a saved search into a fresh space)

The normal import/export flow shows a screen which allows users to choose a new index pattern or saved search to associate, but this is one of the features that differs between import/export and copy to space.

I have this "missing references" code in place for the sole purpose of showing a more informative tooltip when reviewing the "copy to space" results.

Wouldn't this be all missing references for the entire "object graph" including transitive references?

No, currently, the import/export service only deals with direct references to index patterns and saved searches. No other reference types are checked for this condition on import, and we don't fail if this happens on a transitive reference either. This feels inconsistent to me, but also outside the scope of the "Copy to Space" feature IMO.

);
return <EuiIconTip type={'check'} color={successColor} content={message} />;
}
if (hasMissingRefs) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Were you able to test this functionality somehow? I get a 400 whenever trying...

Copy link
Member Author

Choose a reason for hiding this comment

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

See comment above, I think we're talking about two different scenarios

| UnsuccessfulResponse
| ProcessingResponse;

export function summarizeCopyResult(
Copy link
Contributor

Choose a reason for hiding this comment

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

If we only use this from within x-pack/legacy/plugins/spaces/public/views/management/components/copy_saved_objects_to_space should we move it there?

Copy link
Member Author

Choose a reason for hiding this comment

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

We can...I chose to put it here so that I could test it independently from the React components, and it felt wrong to have this non-component file within the **/components/** directory structure

@legrego
Copy link
Member Author

legrego commented Aug 23, 2019

We also are re-using types and processImportResponse from the saved objects import, which is somewhat awkward. It isn't obvious that internally copy to space is relying upon import/export.

I didn't see it that way - I liked that we weren't duplicating functionality or type definitions for what's effectively a thin wrapper around the import/export feature. It felt to me like we'd be able to see how changes to import/export will impact Copy to Space in the future. Do you have suggestions on how we can improve this? We can divorce the two from a types perspective, but then I feel like it's even less obvious that copy to space relies upon import/export.

Also, when choosing to "overwrite" a saved object, should we change the test of the "Finish" button? It wasn't immediately obvious to me that clicking "overwrite" wasn't enough to actually overwrite it and that we were just marking it to be retried once we hit "Finish".

Sure, that's a good idea.

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

@legrego
Copy link
Member Author

legrego commented Aug 23, 2019

Following a discussion with @kobelb, we decided on the following:

  • We will no longer explain when a copy failed due to "missing references"
  • We will no longer allow a saved object to be copied without it's references (related objects)

These decisions were made after discovering shortcomings in the import/export functionality which would have led to a confusing user experience for the Copy to Space feature.

@legrego
Copy link
Member Author

legrego commented Aug 23, 2019

Also discovered during testing: #43876

Copy link
Contributor

@kobelb kobelb left a comment

Choose a reason for hiding this comment

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

LGTM on green CI

@snide
Copy link
Contributor

snide commented Aug 23, 2019

@legrego I'll have a review / PR for you in a couple hours from the design side.

@snide snide self-requested a review August 23, 2019 17:02
@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Copy link
Contributor

@snide snide left a comment

Choose a reason for hiding this comment

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

I loaded this locally and looked through the code. There are some changes I'd like to make on the design / sass side that I can do on my own. There's nothing in here that looks scary that I would want to hold this PR up for.

Since we're got the green, I'm ok with a merge, and I'll do my design pass as a separate concern before freeze.

@legrego legrego merged commit 6a9844c into elastic:master Aug 23, 2019
@legrego legrego deleted the copy-to-space-ui branch August 23, 2019 18:24
legrego added a commit to legrego/kibana that referenced this pull request Aug 23, 2019
@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature:Security/Spaces Platform Security - Spaces feature release_note:enhancement Team:Security Platform Security: Auth, Users, Roles, Spaces, Audit Logging, etc t// v7.4.0 v8.0.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Saved Object Management - Copy to Space

7 participants