Skip to content

Commit

Permalink
[4373] Allow backend definition of ExpandAll tool in the explorer
Browse files Browse the repository at this point in the history
Bug: #4373
Signed-off-by: Gwendal Daniel <[email protected]>
  • Loading branch information
gdaniel committed Jan 6, 2025
1 parent f11f370 commit c92f64d
Show file tree
Hide file tree
Showing 62 changed files with 2,991 additions and 1,682 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@

=== Breaking changes

- https://github.com/eclipse-sirius/sirius-web/issues/4373[#4373] [trees] `onExpand` and `onExpandAll` is removed from `Tree` and all the tree components.
It is now possible to expand a tree item by using `onExpandedElementChange`.
The expand all entry (and its implementation) has been moved to Sirius Web as a contribution.

=== Dependency update

Expand Down Expand Up @@ -43,6 +46,10 @@ Specifiers can contribute dedicated AQL services for this feature using implemen
- https://github.com/eclipse-sirius/sirius-web/issues/4368[#4368] [sirius-web] Add GraphQL subscription exception handler
- [charts] Make the npm package `sirius-components-charts` use the strict version of our TypeScript configuration
- [trees] Make the npm package `sirius-components-trees` use the strict version of our TypeScript configuration
- https://github.com/eclipse-sirius/sirius-web/issues/4373[#4373] [trees] Allow backend definition of ExpandAll tool in the explorer
Specifiers can now create `CustomTreeItemContextMenuEntry` instances in the view DSL to indicate to use a frontend component with a given identifier as contextual menu entry.
This information is passed to the frontend via a dedicated identifier in `SingleClickTreeItemContextMenuEntry#id`.
The _ExpandAll_ tool is now a Sirius Web contribution that can be enabled via this mechanism.


== v2025.1.0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023, 2024 Obeo.
* Copyright (c) 2023, 2025 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand All @@ -11,10 +11,16 @@
* Obeo - initial API and implementation
*******************************************************************************/

import { TreeItemActionProps, TreeView } from '@eclipse-sirius/sirius-components-trees';
import {
GQLGetExpandAllTreePathVariables,
GQLTreeItem,
TreeItemActionProps,
TreeView,
useExpandAll,
} from '@eclipse-sirius/sirius-components-trees';
import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore';
import IconButton from '@mui/material/IconButton';
import { useState } from 'react';
import { useState, useEffect } from 'react';
import { makeStyles } from 'tss-react/mui';
import { ModelBrowserFilterBar } from './ModelBrowserFilterBar';
import { ModelBrowserTreeViewProps, ModelBrowserTreeViewState } from './ModelBrowserTreeView.types';
Expand Down Expand Up @@ -92,8 +98,40 @@ export const ModelBrowserTreeView = ({
);
};

const WidgetReferenceTreeItemAction = ({ onExpandAll, item, isHovered }: TreeItemActionProps) => {
if (!onExpandAll || !item || !item.hasChildren || !isHovered) {
const WidgetReferenceTreeItemAction = ({
editingContextId,
treeId,
item,
isHovered,
expanded,
maxDepth,
onExpandedElementChange,
}: TreeItemActionProps) => {
const {
getExpandAllTreePath,
expanded: newExpanded,
maxDepth: newMaxDepth,
loading,
} = useExpandAll(expanded, maxDepth);

useEffect(() => {
if (!loading) {
if (newExpanded && newMaxDepth >= 0) {
onExpandedElementChange(newExpanded, newMaxDepth);
}
}
}, [newExpanded, newMaxDepth, loading]);

const onExpandAll = (treeItem: GQLTreeItem) => {
const variables: GQLGetExpandAllTreePathVariables = {
editingContextId,
treeId,
treeItemId: treeItem.id,
};
getExpandAllTreePath({ variables });
};

if (!item || !isHovered) {
return null;
}
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* Copyright (c) 2024, 2025 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand All @@ -11,10 +11,16 @@
* Obeo - initial API and implementation
*******************************************************************************/
import { DiagramDialogVariable } from '@eclipse-sirius/sirius-components-diagrams';
import { TreeItemActionProps, TreeView } from '@eclipse-sirius/sirius-components-trees';
import {
GQLGetExpandAllTreePathVariables,
GQLTreeItem,
TreeItemActionProps,
TreeView,
useExpandAll,
} from '@eclipse-sirius/sirius-components-trees';
import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore';
import IconButton from '@mui/material/IconButton';
import { useState } from 'react';
import { useState, useEffect } from 'react';
import { makeStyles } from 'tss-react/mui';
import { SelectionDialogTreeViewProps, SelectionDialogTreeViewState } from './SelectionDialogTreeView.types';
import { useSelectionDialogTreeSubscription } from './useSelectionDialogTreeSubscription';
Expand Down Expand Up @@ -73,8 +79,40 @@ export const SelectionDialogTreeView = ({
);
};

const SelectionDialogTreeItemAction = ({ onExpandAll, item, isHovered }: TreeItemActionProps) => {
if (!onExpandAll || !item || !item.hasChildren || !isHovered) {
const SelectionDialogTreeItemAction = ({
editingContextId,
treeId,
item,
isHovered,
expanded,
maxDepth,
onExpandedElementChange,
}: TreeItemActionProps) => {
const {
getExpandAllTreePath,
expanded: newExpanded,
maxDepth: newMaxDepth,
loading,
} = useExpandAll(expanded, maxDepth);

useEffect(() => {
if (!loading) {
if (newExpanded && newMaxDepth >= 0) {
onExpandedElementChange(newExpanded, newMaxDepth);
}
}
}, [newExpanded, newMaxDepth, loading]);

const onExpandAll = (treeItem: GQLTreeItem) => {
const variables: GQLGetExpandAllTreePathVariables = {
editingContextId,
treeId,
treeItemId: treeItem.id,
};
getExpandAllTreePath({ variables });
};

if (!item || !isHovered) {
return null;
}
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* Copyright (c) 2024, 2025 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -38,7 +38,8 @@ public PersistentRepresentationMetadataProvider(IRepresentationMetadataSearchSer

@Override
public Optional<RepresentationMetadata> getMetadata(String representationId) {
return new UUIDParser().parse(representationId)
// Remove the parameters from the representationId to extract the actual UUID.
return new UUIDParser().parse(representationId.split("\\?")[0])
.flatMap(this.representationMetadataSearchService::findMetadataById)
.map(representation -> RepresentationMetadata.newRepresentationMetadata(representation.getId().toString())
.kind(representation.getKind())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* Copyright (c) 2024, 2025 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -250,6 +250,11 @@ private List<TreeItemContextMenuEntry> getContextMenuEntries() {
.body(callService.build())
.build();

return List.of(helpMenuEntry, toggleAbstractMenuEntry);
var expandAllMenuEntry = new TreeBuilders().newCustomTreeItemContextMenuEntry()
.contributionId("siriusweb_treeItem#backendContextMenuEntry_expandAll")
.preconditionExpression(AQL_TRUE)
.build();

return List.of(expandAllMenuEntry, helpMenuEntry, toggleAbstractMenuEntry);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*******************************************************************************
* Copyright (c) 2025 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.web.application.views.explorer.services;

import java.util.List;
import java.util.Objects;

import org.eclipse.sirius.components.collaborative.trees.api.ITreeItemContextMenuEntryProvider;
import org.eclipse.sirius.components.collaborative.trees.dto.ITreeItemContextMenuEntry;
import org.eclipse.sirius.components.collaborative.trees.dto.SingleClickTreeItemContextMenuEntry;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.trees.Tree;
import org.eclipse.sirius.components.trees.TreeItem;
import org.eclipse.sirius.components.trees.description.TreeDescription;
import org.springframework.stereotype.Service;

/**
* Provides the context menu entries for tree items in the explorer.
*
* @author gdaniel
*/
@Service
public class ExplorerTreeItemContextMenuEntryProvider implements ITreeItemContextMenuEntryProvider {

@Override
public boolean canHandle(IEditingContext editingContext, TreeDescription treeDescription, Tree tree, TreeItem treeItem) {
return tree.getId().startsWith(ExplorerDescriptionProvider.PREFIX)
&& Objects.equals(tree.getDescriptionId(), ExplorerDescriptionProvider.DESCRIPTION_ID);
}

@Override
public List<ITreeItemContextMenuEntry> getTreeItemContextMenuEntries(IEditingContext editingContext, TreeDescription treeDescription, Tree tree, TreeItem treeItem) {
if (treeItem.isHasChildren()) {
return List.of(new SingleClickTreeItemContextMenuEntry("siriusweb_treeItem#backendContextMenuEntry_expandAll", "", List.of()));
} else {
return List.of();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*******************************************************************************
* Copyright (c) 2025 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.web.application.views.tree;

import java.util.List;

import org.eclipse.sirius.components.collaborative.trees.api.ITreeItemContextMenuEntryProvider;
import org.eclipse.sirius.components.collaborative.trees.dto.ITreeItemContextMenuEntry;
import org.eclipse.sirius.components.collaborative.trees.dto.SingleClickTreeItemContextMenuEntry;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.trees.Tree;
import org.eclipse.sirius.components.trees.TreeItem;
import org.eclipse.sirius.components.trees.description.TreeDescription;
import org.springframework.stereotype.Service;

/**
* Provides the context menu entries for tree items in the domain explorer.
*
* @author gdaniel
*/
@Service
public class DomainTreeItemContextMenuEntryProvider implements ITreeItemContextMenuEntryProvider {

@Override
public boolean canHandle(IEditingContext editingContext, TreeDescription treeDescription, Tree tree, TreeItem treeItem) {
return treeDescription.getId().equals(DomainTreeRepresentationDescriptionProvider.DESCRIPTION_ID);
}

@Override
public List<ITreeItemContextMenuEntry> getTreeItemContextMenuEntries(IEditingContext editingContext, TreeDescription treeDescription, Tree tree, TreeItem treeItem) {
if (treeItem.isHasChildren()) {
return List.of(new SingleClickTreeItemContextMenuEntry("siriusweb_treeItem#backendContextMenuEntry_expandAll", "", List.of()));
} else {
return List.of();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
import org.eclipse.sirius.web.application.views.explorer.services.ExplorerDescriptionProvider;
import org.eclipse.sirius.web.data.StudioIdentifiers;
import org.eclipse.sirius.web.tests.graphql.ExplorerDescriptionsQueryRunner;
import org.eclipse.sirius.web.tests.graphql.FetchTreeItemContextMenuEntryDataQueryRunner;
import org.eclipse.sirius.web.tests.graphql.SingleClickTreeItemContextMenuEntryMutationRunner;
import org.eclipse.sirius.web.tests.graphql.TreeItemContextMenuQueryRunner;
import org.eclipse.sirius.web.tests.graphql.FetchTreeItemContextMenuEntryDataQueryRunner;
import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState;
import org.eclipse.sirius.web.tests.services.explorer.ExplorerEventSubscriptionRunner;
import org.eclipse.sirius.web.tests.services.representation.RepresentationIdBuilder;
Expand Down Expand Up @@ -140,14 +140,18 @@ public void givenAStudioWhenTheContextMenuActionsAreRequestedOnAnEntityThenTheCo
var result = this.treeItemContextMenuQueryRunner.run(variables);

Object document = Configuration.defaultConfiguration().jsonProvider().parse(result);

List<String> actionLabels = JsonPath.read(document, "$.data.viewer.editingContext.representation.description.contextMenu[*].label");
assertThat(actionLabels).isNotEmpty().hasSize(2);
assertThat(actionLabels.get(0)).isEqualTo("Help");
assertThat(actionLabels.get(1)).isEqualTo("Toggle abstract");

helpId.set(JsonPath.read(document, "$.data.viewer.editingContext.representation.description.contextMenu[0].id"));
toggleAbstractAction.set(JsonPath.read(document, "$.data.viewer.editingContext.representation.description.contextMenu[1].id"));
List<String> actionIds = JsonPath.read(document, "$.data.viewer.editingContext.representation.description.contextMenu[*].id");
assertThat(actionLabels).isNotEmpty().hasSize(3);
assertThat(actionIds).isNotEmpty().hasSize(3);
// The ExpandAll action doesn't have a label, it only contains the ID of the frontend component to use.
assertThat(actionLabels.get(0)).isEqualTo("");
assertThat(actionIds.get(0)).isEqualTo("siriusweb_treeItem#backendContextMenuEntry_expandAll");
assertThat(actionLabels.get(1)).isEqualTo("Help");
assertThat(actionLabels.get(2)).isEqualTo("Toggle abstract");

helpId.set(JsonPath.read(document, "$.data.viewer.editingContext.representation.description.contextMenu[1].id"));
toggleAbstractAction.set(JsonPath.read(document, "$.data.viewer.editingContext.representation.description.contextMenu[2].id"));
};

// 4- invoke fetch action data query to retrieve the fetch action data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ import { OmniboxButton } from '@eclipse-sirius/sirius-components-omnibox';
import { PortalRepresentation } from '@eclipse-sirius/sirius-components-portals';
import { SelectionDialog } from '@eclipse-sirius/sirius-components-selection';
import { TableRepresentation } from '@eclipse-sirius/sirius-components-tables';
import { TreeRepresentation, treeItemContextMenuEntryExtensionPoint } from '@eclipse-sirius/sirius-components-trees';
import {
TreeRepresentation,
treeItemContextMenuEntryExtensionPoint,
treeItemBackendContextMenuEntryExtensionPoint,
} from '@eclipse-sirius/sirius-components-trees';
import { ValidationView } from '@eclipse-sirius/sirius-components-validation';
import {
GQLReferenceWidget,
Expand All @@ -62,6 +66,7 @@ import { NavigationBarRightContributionProps } from '../navigationBar/Navigation
import { navigationBarRightContributionExtensionPoint } from '../navigationBar/NavigationBarExtensionPoints';
import { OnboardArea } from '../onboarding/OnboardArea';
import { DiagramTreeItemContextMenuContribution } from '../views/edit-project/DiagramTreeItemContextMenuContribution';
import { ExpandAllTreeItemContextMenuContribution } from '../views/edit-project/ExpandAllTreeItemContextMenuContribution';
import { DocumentTreeItemContextMenuContribution } from '../views/edit-project/DocumentTreeItemContextMenuContribution';
import { DownloadProjectMenuEntryContribution } from '../views/edit-project/EditProjectNavbar/DownloadProjectMenuEntryContribution';
import { editProjectNavbarMenuEntryExtensionPoint } from '../views/edit-project/EditProjectNavbar/EditProjectNavbarMenuExtensionPoints';
Expand Down Expand Up @@ -275,6 +280,18 @@ defaultExtensionRegistry.addComponent(treeItemContextMenuEntryExtensionPoint, {
Component: DiagramTreeItemContextMenuContribution,
});

/*******************************************************************************
*
* Tree item backend context menu
*
* Used to register new components in the tree item context menu that will be displayed by the backend
*
*******************************************************************************/
defaultExtensionRegistry.addComponent(treeItemBackendContextMenuEntryExtensionPoint, {
identifier: `siriusweb_${treeItemBackendContextMenuEntryExtensionPoint.identifier}_expandAll`,
Component: ExpandAllTreeItemContextMenuContribution,
});

/*******************************************************************************
*
* Apollo client options configurer
Expand Down
Loading

0 comments on commit c92f64d

Please sign in to comment.