-
Notifications
You must be signed in to change notification settings - Fork 57
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
[3763] Implements the Selection Dialog TreeView #3870
Conversation
c2a90ac
to
0e467aa
Compare
af8ac8a
to
c59f3a4
Compare
0e467aa
to
91e4ae5
Compare
91e4ae5
to
45307c2
Compare
c59f3a4
to
dd123a8
Compare
45307c2
to
f27aab5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The coverage code fails. You should add some tests.
With this PR, it is not possible anymore to create a SelectionDialog with a list. Only trees are available. I didn't remember we talked about removing the support of the list to let only trees.
Furthermore, In the case we have decided that we only support trees in SelectionDialog, what about existing SelectionDialog with list? It seems they are not migrated.
Yes I know about the code coverage. I see what I can do but for the selection.graphql module it will be complicated to retrieve 100% About the Tree, we discussed it with Stephane (the ADR will be updated). And we decided to keep only the Tree since if we want a flat list, we can just provide all elements as roots. |
Ok to let only the tree in this case, but it seems the migration does not work. |
Ok I will have a look. |
a37c36e
to
539f83d
Compare
dd123a8
to
251994c
Compare
c4cb422
to
92bc756
Compare
251994c
to
eb4c34b
Compare
92bc756
to
b6e8baf
Compare
I've rebased the PR to prepare its review, I'll try to review it this afternoon |
6e5bf9e
to
56eeef2
Compare
665d5ad
to
94f530d
Compare
7a07b30
to
36df83b
Compare
36df83b
to
bdb118c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll perform the minor changes necessary and update the PR to merge it
* | ||
* Contributors: | ||
* Obeo - initial API and implementation | ||
*******************************************************************************/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong location for this class, this is not an API and this is related to diagrams
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
private Boolean hasChildren(AQLInterpreter interpreter, SelectionDialogTreeDescription selectionDialogTreeDescription, VariableManager variableManager, Function<VariableManager, Boolean> isSelectableProvider) { | ||
boolean hasChildren = false; | ||
Object self = variableManager.getVariables().get(VariableManager.SELF); | ||
hasChildren = !this.computeChildrenFromExpression(variableManager, interpreter, selectionDialogTreeDescription).isEmpty(); | ||
return hasChildren && this.hasCompatibleDescendants(interpreter, selectionDialogTreeDescription, variableManager, self, false, isSelectableProvider); | ||
} | ||
|
||
private boolean hasCompatibleDescendants(AQLInterpreter interpreter, SelectionDialogTreeDescription selectionDialogTreeDescription, VariableManager variableManager, Object object, boolean isDescendant, Function<VariableManager, Boolean> isSelectableProvider) { | ||
VariableManager childVariableManager = variableManager.createChild(); | ||
childVariableManager.put(VariableManager.SELF, object); | ||
return isDescendant && isSelectableProvider.apply(childVariableManager) | ||
|| this.computeChildrenFromExpression(childVariableManager, interpreter, selectionDialogTreeDescription).stream().anyMatch(eContent -> this.hasCompatibleDescendants(interpreter, selectionDialogTreeDescription, childVariableManager, eContent, true, isSelectableProvider)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is MASSIVELY expensive for something which shouldn't be. You can't start recursively navigating the whole editing context like that and certainly not simply to answer the question "hasChildren". If the specifier choses to display useless data in the dialog that's their choice not ours.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So for you it is the specifier responsibility to define this rules?
It can be complicated to implement in the studio
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's consider the following tree:
- A
- B
- C
- D
- E
- F (with 1 million elements under F)
For every semantic change in the workbench, for each tree item displayed (here A, B, C, D, E, F) we will execute hasChildren
(so 6 times per refresh) which will each perform an eAllContents
on the whole tree just because we want to be smarter than the specifier who has told us to display something by trying to not display potentially useless stuff. That's a massive performance penalty for everybody on the whole project just because ONE person has opened the selection dialog.
If the specifier tells us to display something, we display it. I can understand the intention behind this feature but we can't accept such a performance it for something like that. On top of it, I disagree with the need for such feature. One may need to see the children of an element in order to decide which one should be selected. I don't see why we should decide to hide something that the specifier has explicitly told us to display thanks to the childrenExpression
. If the specifiers wants to perform eAllContents
everywhere that's their choice not ours.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the arguments. For information, I used the same logic we already have in org.eclipse.sirius.components.collaborative.widget.reference.browser.ModelBrowsersDescriptionProvider.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(●__● )
In that case, I may have missed something there. I'll look into it...
( `▽´)Ψ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<artifactId> | ||
sirius-components-collaborative-trees | ||
</artifactId> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be on one line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
if (input instanceof SelectionDescriptionMessageInput selectionDescriptionMessageInput) { | ||
String targetObjectId = selectionDescriptionMessageInput.targetObjectId(); | ||
Optional<Object> optionalTargetObject = this.objectService.getObject(editingContext, targetObjectId); | ||
if (optionalTargetObject.isPresent()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You still need to emit a payload in all cases, including if we do not enter the "if"
if (!loading && selectionDescription) { | ||
setState((prevState) => ({ | ||
...prevState, | ||
message: selectionDescription.message, | ||
treeDescriptionId: selectionDescription.treeDescription.id, | ||
})); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll look a bit more into the code but you don't seems to need a state and useEffect just for that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, it just a query so the component will be rerender a soon as we receive the data ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
@@ -80,59 +31,48 @@ export const SelectionDialog = ({ | |||
onClose, | |||
onFinish, | |||
}: DiagramDialogComponentProps) => { | |||
const { classes } = useSelectionObjectModalStyles(); | |||
const initialState: DiagramDialogState = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SelectionDialogState
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
targetObjectId: string; | ||
} | ||
|
||
export interface SelectionDescription { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GQLSelectionDescription to keep indicating that this type comes from the backend
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
treeDescription: TreeDescription; | ||
} | ||
|
||
export interface TreeDescription { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GQLTreeDescription
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
treeDescriptionId: string; | ||
message: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
string or null to properly identify that you don't have the relevant data. Your code only works because if(aVariableContainingAnEmptyString)
evaluates to false
and it does not enter the if
. That's a very narrow assumption that empty string equals false.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And you probably don't need this in the state too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The state and the useEffect were indeed not needed
const useTreeStyle = makeStyles()((theme) => ({ | ||
borderStyle: { | ||
border: '1px solid', | ||
borderColor: theme.palette.grey[500], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
theme.palette.divider to stay with the same style as the rest of the application
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
result.removeIf(object -> { | ||
if (object instanceof EObject eObject) { | ||
VariableManager childVariableManager = variableManager.createChild(); | ||
childVariableManager.put(VariableManager.SELF, eObject); | ||
return !isSelectableProvider.apply(childVariableManager) && !this.hasChildren(interpreter, selectionDialogTreeDescription, childVariableManager, isSelectableProvider); | ||
} else { | ||
return false; | ||
} | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't decide that, let the specifiers display what they want. And you can't decide that without the MASSIVE performance impact from before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
I'll wait for the build, squash the commits and merge the PR |
…eView Bug: #3763 Signed-off-by: Florian Barbin <[email protected]>
Signed-off-by: Stéphane Bégaudeau <[email protected]>
3729fad
to
1d4158d
Compare
I'll wait for the build and merge it 👍 |
Bug: #3763
Pull request template
General purpose
What is the main goal of this pull request?
Project management
priority:
andpr:
labels been added to the pull request? (In case of doubt, start with the labelspriority: low
andpr: to review later
)area:
,difficulty:
,type:
)CHANGELOG.adoc
been updated to reference the relevant issues?CHANGELOG.adoc
? (Including changes in the GraphQL API)CHANGELOG.adoc
? For example indoc/screenshots/2022.5.0-my-new-feature.png
Architectural decision records (ADR)
[doc]
?CHANGELOG.adoc
?Dependencies
CHANGELOG.adoc
?CHANGELOG.adoc
?Frontend
This section is not relevant if your contribution does not come with changes to the frontend.
General purpose
Typing
We need to improve the typing of our code, as such, we require every contribution to come with proper TypeScript typing for both changes contributing new files and those modifying existing files.
Please ensure that the following statements are true for each file created or modified (this may require you to improve code outside of your contribution).
useMutation<DATA_TYPE, VARIABLE_TYPE>(…)
useQuery<DATA_TYPE, VARIABLE_TYPE>(…)
useSubscription<DATA_TYPE, VARIABLE_TYPE>(…)
useMachine<CONTEXT_TYPE, EVENTS_TYPE>(…)
useState<STATE_TYPE>(…)
?.
(if the GraphQL API specifies that a field cannot benull
, do not treat it has potentiallynull
for example)let diagram: Diagram | null = null;
)Backend
This section is not relevant if your contribution does not come with changes to the backend.
General purpose
Architecture
Review
How to test this PR?
import both :
testSelectionDialogModel.zip
TestSelectionDialogStudio.zip
Open the diagram in testSelectionDialogModel
Use the selection tool
Select an existing element (only entity1 are selectable)
Perform finish : the element should be renamed
Has the Kiwi TCMS test suite been updated with tests for this contribution?