Skip to content

feat: apply initial layout COMPASS-9432 #7047

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

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open

Conversation

paula-stacho
Copy link
Contributor

@paula-stacho paula-stacho commented Jun 20, 2025

Description

  1. The new diagram is created at [-1, -1]
  2. The editor uses applyLayout from the diagramming lib to position the nodes
  3. The initial layout is saved to the store and storage, overriding the initial edit
  4. Once the nodes are ready, the diagram is fit to view
Screenshot 2025-06-20 at 18 31 48

Checklist

  • New tests and/or benchmarks are included
  • Documentation is changed or added
  • If this change updates the UI, screenshots/videos are added and a design review is requested
  • I have signed the MongoDB Contributor License Agreement (https://www.mongodb.com/legal/contributor-agreement)

Motivation and Context

  • Bugfix
  • New feature
  • Dependency update
  • Misc

Open Questions

Dependents

Types of changes

  • Backport Needed
  • Patch (non-breaking change which fixes an issue)
  • Minor (non-breaking change which adds functionality)
  • Major (fix or feature that would cause existing functionality to change)

@github-actions github-actions bot added the feat label Jun 20, 2025
@paula-stacho paula-stacho added the feature flagged PRs labeled with this label will not be included in the release notes of the next release label Jun 20, 2025
@paula-stacho
Copy link
Contributor Author

The layouts work much better now with the dimensions fixed 🎉. But still not exactly as imagined. For example the screenshot is LEFT_RIGHT - I thought this would spread to more columns. STAR creates one column only. Are we doing something wrong or is this expected result? @lchans

@paula-stacho paula-stacho marked this pull request as ready for review June 20, 2025 16:48
@paula-stacho paula-stacho requested a review from a team as a code owner June 20, 2025 16:48
expect(store.getState().diagram?.edits.current).to.have.lengthOf(1);
});
const renderResult = renderWithConnections(
<Provider store={store}>{component}</Provider>,
Copy link
Collaborator

@gribnoysup gribnoysup Jun 23, 2025

Choose a reason for hiding this comment

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

We have helpers for this in compass-testing-library, I strongly suggest you take a look at those. We added these specifically so that we don't need to spend time for similar setup all the time and so that making changes to the plugin internals is easier in the long run (otherwise every time we tinker with plugin system ALL tests might need to be updated accordingly). If those doesn't cover some case you are trying to cover here, please shout this out so that we can provide tools covering those and keep the benefits of a shared testing harness

@mabaasit FYI as you added some helpers here initially.

Copy link
Contributor

Choose a reason for hiding this comment

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

There was an issue i was facing when setting this up, but i don't remember exactly what it was (my guess is TestMongoDBInstanceManager props were not being picked up and it does not support multiple connections). As a result, I had to add testConnections in this file and mock connections implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated the tests helpers in this file, haven't run into any problems here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For now I avoided the problem with store not being fit for that view by replacing the error by empty result. Possibly something we could use in the future - to allow some preparation of the store before rendering the component. We could also provide initial store state but seems more natural (and easier to maintain) to get there with actions.

void applyInitialLayout(storedNodes);
return;
}
setNodes(storedNodes);
Copy link
Collaborator

Choose a reason for hiding this comment

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

The state itself is not an effect here, this is state derived from model, only applying initial layout is an effect

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So this used to be a memo, I changed it to effect so that unpositioned nodes can be ignored (setNodes is not called in that case). Is it too weird? I was considering having a memo + boolean 'areNodesReady' tag as an alternative

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, it's almost always not a good idea to duplicate props to local component state through effects, especially when you have a clear way to derive this, so much so that React has a documentation for that:

When something can be calculated from the existing props or state, don’t put it in state. Instead, calculate it during rendering.

So nodes + areNodesReady + effect that depends on areNodesReady is definitely a cleaner way to do this.

There is honestly an argument to be made about moving this logic to the action itself as it doesn't really depend on UI (meaning actual DOM), is not really doing any application (more specifically it's not really an effect as compared to fitToView for example) just calculates the values for the state that is already in the store and so splitting this logic between React and Redux doesn't give us any meaningful separation of concerns here, while requiring us to jump through some unnecessary hoops to get the state in the right shape. This is a bit of splitting hairs thing, so I think it's fine if we keep it as is and just remove the unnecessary UI state from the equasion.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated

'LEFT_RIGHT'
);
setNodes(positionedNodes);
onApplyInitialLayout(
Copy link
Collaborator

Choose a reason for hiding this comment

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

We are supposed to also fit diagram into view after initial layout gets applied, right? I'm not seeing this happening at the moment

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you, added!

@paula-stacho paula-stacho changed the title feat(COMPASS-9432): apply initial layout feat: apply initial layout COMPASS-9432 Jun 24, 2025
@paula-stacho paula-stacho force-pushed the COMPASS-9432 branch 2 times, most recently from 2ef8837 to 235ab17 Compare June 25, 2025 11:51
},
};
(require.cache[require.resolve('@mongodb-js/diagramming')] as any).exports =
mockDiagramming;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess this isn't possible with something like sinon? Would it be possible/make sense to add a TODO to make the diagramming package itself allow mocking the relevant parts à la dependency injection?

It's a bit unfortunate to have this here, especially because it only targets a single test file right now, but all test files in the same mocha invocation will have these mocks in place

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah. I was writing to explain that sinon wouldn't be enough because there was a problem with ESM/CJS interop. I actually spent some time trying to get a test setup that would import the Diagram correctly before I decided that mocks are fine as we cover the integration in e2e tests.
But as I was writing it hit me that even though the cause was the messed up import, no error was thrown until the imported piece was being used. So taking over the require was an overkill.
Tldr: actually sinon works, thanks for making me rethink!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat feature flagged PRs labeled with this label will not be included in the release notes of the next release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants