Skip to content

Commit 50b575f

Browse files
committed
[1363] Add a menu action that will hide children that don't have children and will reveal the others.
Bug: #1363 Signed-off-by: Michaël Charfadi <michael.charfadi@obeosoft.com>
1 parent 305bdf3 commit 50b575f

File tree

8 files changed

+399
-1
lines changed

8 files changed

+399
-1
lines changed

CHANGELOG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ All existing SysON _DiagramDescriptions_ (i.g. _General View_, _Interconnection
9898
- https://github.com/eclipse-syson/syson/issues/1310[#1310] [metamodel] Revert remove derived flag for `ViewUsage#exposedElement` feature.
9999
- https://github.com/eclipse-syson/syson/issues/1359[#1359] [export] Implement textual export of `ViewUsage`.
100100
- https://github.com/eclipse-syson/syson/issues/1350[#1350] [general-view] Improve _direct edit_ tool on `Feature` to be able to edit `FeatureValue` with basic expressions.
101+
- https://github.com/eclipse-syson/syson/issues/1363[#1363] [general-view] Add a reveal only valued content action on the manage visibility node action modal that will hide children that don't have children and will reveal the others.
101102

102103
=== New features
103104

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Obeo.
3+
* This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v2.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Obeo - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.syson.application.controllers.diagrams.general.view;
14+
import static org.assertj.core.api.Assertions.fail;
15+
import static org.assertj.core.api.Assertions.assertThat;
16+
17+
import java.time.Duration;
18+
import java.util.List;
19+
import java.util.Map;
20+
import java.util.Optional;
21+
import java.util.UUID;
22+
import java.util.concurrent.atomic.AtomicReference;
23+
import java.util.function.Consumer;
24+
25+
import com.jayway.jsonpath.JsonPath;
26+
import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramEventInput;
27+
import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramRefreshedEventPayload;
28+
import org.eclipse.sirius.components.collaborative.diagrams.dto.managevisibility.InvokeManageVisibilityActionInput;
29+
import org.eclipse.sirius.components.core.api.SuccessPayload;
30+
import org.eclipse.sirius.components.diagrams.ViewModifier;
31+
import org.eclipse.sirius.components.diagrams.tests.graphql.GetManageVisibilityActionsQueryRunner;
32+
import org.eclipse.sirius.components.diagrams.tests.graphql.InvokeManageVisibilityActionMutationRunner;
33+
import org.eclipse.sirius.web.application.nodeaction.managevisibility.ManageVisibilityHideAllAction;
34+
import org.eclipse.sirius.web.application.nodeaction.managevisibility.ManageVisibilityRevealAllAction;
35+
import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState;
36+
import org.eclipse.syson.AbstractIntegrationTests;
37+
import org.eclipse.syson.application.data.GeneralViewManageVisibilityTestsProjectData;
38+
import org.eclipse.syson.diagram.general.view.services.nodeactions.managevisibility.GeneralViewManageVisibilityRevealValuedContentAction;
39+
import org.eclipse.syson.services.diagrams.api.IGivenDiagramSubscription;
40+
import org.junit.jupiter.api.BeforeEach;
41+
import org.junit.jupiter.api.DisplayName;
42+
import org.junit.jupiter.api.Test;
43+
import org.springframework.beans.factory.annotation.Autowired;
44+
import org.springframework.boot.test.context.SpringBootTest;
45+
import org.springframework.test.context.jdbc.Sql;
46+
import org.springframework.test.context.jdbc.SqlConfig;
47+
import org.springframework.transaction.annotation.Transactional;
48+
49+
import reactor.core.publisher.Flux;
50+
import reactor.test.StepVerifier;
51+
52+
/**
53+
* Tests the manage visibility node action.
54+
*
55+
* @author mcharfadi
56+
*/
57+
@Transactional
58+
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
59+
public class GVManageVisibilityTests extends AbstractIntegrationTests {
60+
61+
@Autowired
62+
private IGivenInitialServerState givenInitialServerState;
63+
64+
@Autowired
65+
private IGivenDiagramSubscription givenDiagramSubscription;
66+
67+
@Autowired
68+
private GetManageVisibilityActionsQueryRunner getActionsQueryRunner;
69+
70+
@Autowired
71+
private InvokeManageVisibilityActionMutationRunner invokeActionMutationRunner;
72+
73+
@BeforeEach
74+
public void setUp() {
75+
this.givenInitialServerState.initialize();
76+
}
77+
78+
private Flux<DiagramRefreshedEventPayload> givenSubscriptionToGeneralViewDiagram() {
79+
var diagramEventInput = new DiagramEventInput(
80+
UUID.randomUUID(),
81+
GeneralViewManageVisibilityTestsProjectData.EDITING_CONTEXT_ID,
82+
GeneralViewManageVisibilityTestsProjectData.GraphicalIds.DIAGRAM_ID);
83+
return this.givenDiagramSubscription.subscribe(diagramEventInput);
84+
}
85+
86+
@Sql(scripts = { GeneralViewManageVisibilityTestsProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD,
87+
config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED))
88+
@Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED))
89+
@DisplayName("Given a graphical node with some children hidden and some revealed, when invoking the show valued content only, then only the children that have children are visible")
90+
@Test
91+
public void invokeShowOnlyValuedContent() {
92+
var flux = this.givenSubscriptionToGeneralViewDiagram();
93+
var nodeId = new AtomicReference<String>();
94+
Consumer<DiagramRefreshedEventPayload> initialDiagramContentConsumer = payload -> Optional.of(payload)
95+
.ifPresentOrElse(diagramRefreshedEventPayload -> {
96+
var diagram = diagramRefreshedEventPayload.diagram();
97+
assertThat(diagram.getNodes()).hasSize(1);
98+
nodeId.set(diagram.getNodes().get(0).getId());
99+
assertThat(diagram.getNodes().get(0).getChildNodes()).hasSize(5);
100+
var children = diagram.getNodes().get(0).getChildNodes();
101+
assertThat(children.stream().filter(node -> node.getState().equals(ViewModifier.Hidden))).hasSize(5);
102+
assertThat(children.stream().filter(node -> node.getState().equals(ViewModifier.Normal))).hasSize(0);
103+
}, () -> fail("Missing diagram"));
104+
105+
Runnable getActions = () -> {
106+
Map<String, Object> variables = Map.of(
107+
"editingContextId", GeneralViewManageVisibilityTestsProjectData.EDITING_CONTEXT_ID,
108+
"diagramId", GeneralViewManageVisibilityTestsProjectData.GraphicalIds.DIAGRAM_ID,
109+
"diagramElementId", nodeId.get()
110+
);
111+
var result = this.getActionsQueryRunner.run(variables);
112+
List<String> actionsIds = JsonPath.read(result, "$.data.viewer.editingContext.representation.description.manageVisibilityActions[*].id");
113+
List<String> actionsLabels = JsonPath.read(result, "$.data.viewer.editingContext.representation.description.manageVisibilityActions[*].label");
114+
115+
assertThat(actionsIds)
116+
.isNotEmpty()
117+
.contains(ManageVisibilityRevealAllAction.ACTION_ID)
118+
.contains(ManageVisibilityHideAllAction.ACTION_ID)
119+
.contains(GeneralViewManageVisibilityRevealValuedContentAction.ACTION_ID);
120+
121+
assertThat(actionsLabels)
122+
.isNotEmpty()
123+
.contains("Hide all")
124+
.contains("Reveal all")
125+
.contains("Reveal valued content only");
126+
};
127+
128+
Runnable invokeRevealValuedContentAction = () -> {
129+
var input = new InvokeManageVisibilityActionInput(UUID.randomUUID(), GeneralViewManageVisibilityTestsProjectData.EDITING_CONTEXT_ID, GeneralViewManageVisibilityTestsProjectData.GraphicalIds.DIAGRAM_ID, nodeId.get(), GeneralViewManageVisibilityRevealValuedContentAction.ACTION_ID);
130+
var result = this.invokeActionMutationRunner.run(input);
131+
String typename = JsonPath.read(result, "$.data.invokeManageVisibilityAction.__typename");
132+
assertThat(typename).isEqualTo(SuccessPayload.class.getSimpleName());
133+
};
134+
135+
Consumer<DiagramRefreshedEventPayload> updatedAfterRevealDiagramContentMatcher = payload -> Optional.of(payload)
136+
.ifPresentOrElse(diagramRefreshedEventPayload -> {
137+
var diagram = diagramRefreshedEventPayload.diagram();
138+
assertThat(diagram.getNodes()).hasSize(1);
139+
nodeId.set(diagram.getNodes().get(0).getId());
140+
assertThat(diagram.getNodes().get(0).getChildNodes()).hasSize(5);
141+
var children = diagram.getNodes().get(0).getChildNodes();
142+
assertThat(children.stream().filter(node -> node.getState().equals(ViewModifier.Hidden))).hasSize(3);
143+
assertThat(children.stream().filter(node -> node.getState().equals(ViewModifier.Normal))).hasSize(1);
144+
assertThat(children.stream().filter(node -> node.getState().equals(ViewModifier.Faded))).hasSize(1);
145+
}, () -> fail("Missing diagram"));
146+
147+
StepVerifier.create(flux)
148+
.consumeNextWith(initialDiagramContentConsumer)
149+
.then(getActions)
150+
.then(invokeRevealValuedContentAction)
151+
.consumeNextWith(updatedAfterRevealDiagramContentMatcher)
152+
.thenCancel()
153+
.verify(Duration.ofSeconds(10));
154+
}
155+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Obeo.
3+
* This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v2.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Obeo - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.syson.application.data;
14+
15+
/**
16+
* Project data for the "GVManageVisibilityTests" project.
17+
*
18+
* @author mcharfadi
19+
*/
20+
public class GeneralViewManageVisibilityTestsProjectData {
21+
22+
public static final String SCRIPT_PATH = "/scripts/database-content/GeneralView-ManageVisibility.sql";
23+
24+
public static final String EDITING_CONTEXT_ID = "b01d9a82-7f04-46f9-9b49-d69b291ae105";
25+
26+
/**
27+
* Ids of graphical elements.
28+
*/
29+
public static class GraphicalIds {
30+
31+
public static final String DIAGRAM_ID = "621aded7-5bd5-4966-9526-7ff0816dbb63";
32+
33+
}
34+
}

backend/application/syson-application/src/test/resources/scripts/database-content/GeneralView-ManageVisibility.sql

Lines changed: 94 additions & 0 deletions
Large diffs are not rendered by default.

backend/views/syson-diagram-general-view/src/main/java/org/eclipse/syson/diagram/general/view/services/GeneralViewManageVisibilityNodeActionProvider.java renamed to backend/views/syson-diagram-general-view/src/main/java/org/eclipse/syson/diagram/general/view/services/nodeactions/managevisibility/GeneralViewManageVisibilityNodeActionProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Contributors:
1111
* Obeo - initial API and implementation
1212
*******************************************************************************/
13-
package org.eclipse.syson.diagram.general.view.services;
13+
package org.eclipse.syson.diagram.general.view.services.nodeactions.managevisibility;
1414

1515
import org.eclipse.emf.ecore.EClass;
1616
import org.eclipse.emf.ecore.EObject;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Obeo.
3+
* This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v2.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Obeo - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.syson.diagram.general.view.services.nodeactions.managevisibility;
14+
15+
import org.eclipse.sirius.components.collaborative.diagrams.api.nodeactions.IManageVisibilityMenuActionProvider;
16+
import org.eclipse.sirius.components.collaborative.diagrams.dto.managevisibility.ManageVisibilityAction;
17+
import org.eclipse.sirius.components.core.api.IEditingContext;
18+
import org.eclipse.sirius.components.diagrams.IDiagramElement;
19+
import org.eclipse.sirius.components.diagrams.Node;
20+
import org.eclipse.sirius.components.diagrams.description.DiagramDescription;
21+
import org.springframework.stereotype.Service;
22+
23+
import java.util.List;
24+
25+
/**
26+
* Menu action on the manage visibility modal that will reveal children that also have children.
27+
*
28+
* @author mcharfadi
29+
*/
30+
@Service
31+
public class GeneralViewManageVisibilityRevealValuedContentAction implements IManageVisibilityMenuActionProvider {
32+
33+
public static final String ACTION_ID = "manage_visibility_menu_reveal_valued_content_action";
34+
35+
@Override
36+
public boolean canHandle(IEditingContext editingContext, DiagramDescription diagramDescription, IDiagramElement diagramElement) {
37+
return diagramElement instanceof Node node && !node.getChildNodes().isEmpty();
38+
}
39+
40+
@Override
41+
public List<ManageVisibilityAction> handle(IEditingContext editingContext, DiagramDescription diagramDescription, IDiagramElement diagramElement) {
42+
return List.of(new ManageVisibilityAction(ACTION_ID, "Reveal valued content only"));
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Obeo.
3+
* This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v2.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Obeo - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.syson.diagram.general.view.services.nodeactions.managevisibility;
14+
15+
import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramContext;
16+
import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramQueryService;
17+
import org.eclipse.sirius.components.collaborative.diagrams.api.nodeactions.IManageVisibilityMenuActionHandler;
18+
import org.eclipse.sirius.components.core.api.IEditingContext;
19+
import org.eclipse.sirius.components.diagrams.IDiagramElement;
20+
import org.eclipse.sirius.components.diagrams.Node;
21+
import org.eclipse.sirius.components.diagrams.events.HideDiagramElementEvent;
22+
import org.eclipse.sirius.components.representations.IStatus;
23+
import org.eclipse.sirius.components.representations.Success;
24+
import org.springframework.stereotype.Service;
25+
26+
import java.util.HashSet;
27+
import java.util.Objects;
28+
import java.util.Optional;
29+
import java.util.Set;
30+
31+
/**
32+
* Handler for the menu action on the manage visibility modal that will reveal children that also have children.
33+
*
34+
* @author mcharfadi
35+
*/
36+
@Service
37+
public class GeneralViewManageVisibilityRevealValuedContentHandler implements IManageVisibilityMenuActionHandler {
38+
39+
private final IDiagramQueryService diagramQueryService;
40+
41+
public GeneralViewManageVisibilityRevealValuedContentHandler(IDiagramQueryService diagramQueryService) {
42+
this.diagramQueryService = Objects.requireNonNull(diagramQueryService);
43+
}
44+
45+
@Override
46+
public boolean canHandle(IEditingContext editingContext, IDiagramContext diagramContext, IDiagramElement diagramElement, String actionId) {
47+
return actionId.equals(GeneralViewManageVisibilityRevealValuedContentAction.ACTION_ID);
48+
}
49+
50+
@Override
51+
public IStatus handle(IEditingContext editingContext, IDiagramContext diagramContext, IDiagramElement diagramElement, String actionId) {
52+
Optional<Node> optionalNode = this.diagramQueryService.findNodeById(diagramContext.getDiagram(), diagramElement.getId());
53+
Set<String> nodesToReveal = new HashSet<>();
54+
Set<String> nodesToHide = new HashSet<>();
55+
if (optionalNode.isPresent()) {
56+
optionalNode.get().getChildNodes().forEach(node -> {
57+
if (node.getChildNodes().isEmpty()) {
58+
nodesToHide.add(node.getId());
59+
} else {
60+
nodesToReveal.add(node.getId());
61+
}
62+
});
63+
diagramContext.getDiagramEvents().add(new HideDiagramElementEvent(nodesToReveal, false));
64+
diagramContext.getDiagramEvents().add(new HideDiagramElementEvent(nodesToHide, true));
65+
}
66+
return new Success();
67+
}
68+
69+
}

doc/content/modules/user-manual/pages/release-notes/2025.6.0.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ image::view-usage-graphical-contents.png[ViewUsage graphical contents, width=65%
6060

6161
- `ManageVisibility` node action may now be displayed from the _General View_ on `Definition` and `Usage` graphical nodes.
6262
This node action open a modal that can be used to reveal or hide the graphical node children's.
63+
Menu actions can be used to `reveal all content`, `reveal valued content only` or `hide all content`.
6364

6465
image::release-notes-manage-visibility.png[Manage Visibility modal, width=65%,height=65%]
6566

0 commit comments

Comments
 (0)