Skip to content

Commit

Permalink
[2252] Add the possibility to contribute component tools in the palette
Browse files Browse the repository at this point in the history
Bug: #2252
Signed-off-by: Florian ROUËNÉ <florian.rouene@obeosoft.com>
  • Loading branch information
frouene authored and sbegaudeau committed Sep 11, 2023
1 parent 43efc4f commit 1b57f6f
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 38 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ It's now possible to provide _referenceKind_ to only get the `ChildCreationDescr
- https://github.com/eclipse-sirius/sirius-web/issues/2253[#2253] [diagram] The indroduction of ToolSection in palette, change the _DiagramDescription_ structure by adding a new level _Palette_ instead of _[ToolSection]_.
Note that _palette_ will be removed in short-term from the _DiagramDescription_.
- https://github.com/eclipse-sirius/sirius-web/issues/2329[#2329] [form] Split of `sirius-components-widget-reference` to extract EMF-related code into a new module `sirius-components-collaborative-widget-reference`.

- https://github.com/eclipse-sirius/sirius-web/issues/2252[#2252] [diagram] The support for React Flow based diagrams now require a `DiagramPaletteToolContext` in order to contribute custom palette tool.

=== Dependency update

Expand Down Expand Up @@ -85,6 +85,8 @@ They can however also be used independently (e.g. a single _If_ outside of a _Fo
Note that this first version has a known limitation: _FormDescriptions_ which use _For_ or _If_ elements can not be reliably edited using the _Form Description Editor_.
This will be fixed in the next version.
- https://github.com/eclipse-sirius/sirius-web/issues/2254[#2254] [diagram] Add the possibility to specify precondition on diagram tools
- https://github.com/eclipse-sirius/sirius-web/issues/2252[#2252] [diagram] It's now possible to contribute custom frontend-defined tools in a React Flow diagram palette.
To illustrate this new feature, we contribute a new tool on the _Papaya Diagram_, it's available only on _OperationalActivity_ and it simply opens a dialog with the node label content.

=== Improvements

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@
*******************************************************************************/

export { DiagramRepresentation } from './representation/DiagramRepresentation';
export { DiagramPaletteToolContext } from './renderer/palette/DiagramPaletteToolContext';
export type { DiagramPaletteToolContextValue } from './renderer/palette/DiagramPalette.types';
export { DiagramPaletteToolContribution } from './renderer/palette/DiagramPaletteToolContribution';
export type { DiagramPaletteToolContributionComponentProps } from './renderer/palette/DiagramPaletteToolContribution.types';
export type { NodeData } from './renderer/DiagramRenderer.types';
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
*******************************************************************************/

import { ReactNode } from 'react';
import { DiagramPaletteToolContributionProps } from './DiagramPaletteToolContribution.types';

export type DiagramPaletteToolContextValue = React.ReactElement<DiagramPaletteToolContributionProps>[];

export interface DiagramPaletteProps {
targetObjectId: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*******************************************************************************
* Copyright (c) 2023 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
*******************************************************************************/
import React from 'react';
import { DiagramPaletteToolContextValue } from './DiagramPalette.types';

export const DiagramPaletteToolContext = React.createContext<DiagramPaletteToolContextValue>([]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*******************************************************************************
* Copyright (c) 2023 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
*******************************************************************************/

import { DiagramPaletteToolContributionProps } from './DiagramPaletteToolContribution.types';

export const DiagramPaletteToolContribution = ({}: DiagramPaletteToolContributionProps) => {
return null; // Do nothing on purpose
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2023 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
*******************************************************************************/

export interface DiagramPaletteToolContributionProps {
canHandle: (diagramId: string, diagramElementId: string) => boolean;
component: (props: DiagramPaletteToolContributionComponentProps) => JSX.Element | null;
}

export interface DiagramPaletteToolContributionComponentProps {
diagramElementId: string;
key: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ import IconButton from '@material-ui/core/IconButton';
import { makeStyles } from '@material-ui/core/styles';
import TonalityIcon from '@material-ui/icons/Tonality';
import VisibilityOffIcon from '@material-ui/icons/VisibilityOff';
import { useCallback, useContext, useEffect, useState } from 'react';
import React, { useCallback, useContext, useEffect, useState } from 'react';
import { useEdges, useNodes } from 'reactflow';
import { DiagramContext } from '../../contexts/DiagramContext';
import { DiagramContextValue } from '../../contexts/DiagramContext.types';
import { Tool } from '../Tool';
import { useFadeDiagramElements } from '../fade/useFadeDiagramElements';
import { useHideDiagramElements } from '../hide/useHideDiagramElements';
import { Tool } from '../Tool';
import { DiagramPaletteToolContextValue } from './DiagramPalette.types';
import { DiagramPaletteToolContext } from './DiagramPaletteToolContext';
import { DiagramPaletteToolContributionComponentProps } from './DiagramPaletteToolContribution.types';
import {
ContextualPaletteStyleProps,
GQLCollapsingState,
Expand Down Expand Up @@ -166,13 +169,19 @@ export const Palette = ({ diagramElementId, onDirectEditClick, isDiagramElementP
const edges = useEdges();
const { diagramId, editingContextId } = useContext<DiagramContextValue>(DiagramContext);

const diagramPaletteToolComponents = useContext<DiagramPaletteToolContextValue>(DiagramPaletteToolContext)
.filter((contribution) => contribution.props.canHandle(diagramId, diagramElementId))
.map((contribution) => contribution.props.component);

const toolCount =
(palette
? palette.tools.filter(isSingleClickOnDiagramElementTool).length +
palette.toolSections.filter(
(toolSection) => toolSection.tools.filter(isSingleClickOnDiagramElementTool).length > 0
).length
: 0) + (isDiagramElementPalette ? 2 : 0);
: 0) +
(isDiagramElementPalette ? 2 : 0) +
diagramPaletteToolComponents.length;
const classes = usePaletteStyle({ toolCount });

const [getPalette, { loading: paletteLoading, data: paletteData, error: paletteError }] = useLazyQuery<
Expand Down Expand Up @@ -322,6 +331,13 @@ export const Palette = ({ diagramElementId, onDirectEditClick, isDiagramElementP
{palette?.toolSections.map((toolSection) => (
<ToolSection toolSection={toolSection} onToolClick={handleToolClick} key={toolSection.id} />
))}
{diagramPaletteToolComponents.map((component, index) => {
const props: DiagramPaletteToolContributionComponentProps = {
diagramElementId,
key: index.toString(),
};
return React.createElement(component, props);
})}
{isDiagramElementPalette ? (
<>
<IconButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
*******************************************************************************/
import { gql, useQuery } from '@apollo/client';
import { Representation, Toast, Workbench, WorkbenchViewContribution } from '@eclipse-sirius/sirius-components-core';
import {
DiagramPaletteToolContext,
DiagramPaletteToolContextValue,
DiagramPaletteToolContribution,
NodeData,
} from '@eclipse-sirius/sirius-components-diagrams-reactflow';
import { DetailsView, RelatedElementsView, RepresentationsView } from '@eclipse-sirius/sirius-components-forms';
import {
ExplorerView,
Expand All @@ -25,8 +31,8 @@ import {
} from '@eclipse-sirius/sirius-components-trees';
import { ValidationView } from '@eclipse-sirius/sirius-components-validation';
import Grid from '@material-ui/core/Grid';
import Typography from '@material-ui/core/Typography';
import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import AccountTreeIcon from '@material-ui/icons/AccountTree';
import Filter from '@material-ui/icons/Filter';
import LinkIcon from '@material-ui/icons/Link';
Expand All @@ -35,6 +41,7 @@ import WarningIcon from '@material-ui/icons/Warning';
import { useMachine } from '@xstate/react';
import { useEffect } from 'react';
import { generatePath, useHistory, useParams, useRouteMatch } from 'react-router-dom';
import { useNodes } from 'reactflow';
import { NavigationBar } from '../../navigationBar/NavigationBar';
import { OnboardArea } from '../../onboarding/OnboardArea';
import { DiagramTreeItemContextMenuContribution } from './DiagramTreeItemContextMenuContribution';
Expand All @@ -44,14 +51,15 @@ import { EditProjectViewParams, GQLGetProjectQueryData, GQLGetProjectQueryVariab
import {
EditProjectViewContext,
EditProjectViewEvent,
editProjectViewMachine,
HandleFetchedProjectEvent,
HideToastEvent,
SchemaValue,
SelectRepresentationEvent,
ShowToastEvent,
editProjectViewMachine,
} from './EditProjectViewMachine';
import { ObjectTreeItemContextMenuContribution } from './ObjectTreeItemContextMenuContribution';
import { PapayaOperationActivityLabelDetailToolContribution } from './ToolContributions/PapayaOperationActivityLabelDetailToolContribution';
import { NewDocumentModalContribution } from './TreeToolBarContributions/NewDocumentModalContribution';
import { UploadDocumentModalContribution } from './TreeToolBarContributions/UploadDocumentModalContribution';

Expand Down Expand Up @@ -163,42 +171,60 @@ export const EditProjectView = () => {
<TreeToolBarContribution component={NewDocumentModalContribution} />,
<TreeToolBarContribution component={UploadDocumentModalContribution} />,
];
const diagramPaletteToolContributions: DiagramPaletteToolContextValue = [
<DiagramPaletteToolContribution
canHandle={(_diagramId, diagramElementId) => {
const nodes = useNodes<NodeData>();
const targetedNode = nodes.find((node) => node.id === diagramElementId);
if (targetedNode) {
return (
targetedNode.data.targetObjectKind ===
'siriusComponents://semantic?domain=papaya_operational_analysis&entity=OperationalActivity'
);
}
return false;
}}
component={PapayaOperationActivityLabelDetailToolContribution}
/>,
];

main = (
<TreeItemContextMenuContext.Provider value={treeItemContextMenuContributions}>
<TreeToolBarContext.Provider value={treeToolBarContributions}>
<Workbench
editingContextId={project.currentEditingContext.id}
initialRepresentationSelected={representation}
onRepresentationSelected={onRepresentationSelected}
mainAreaComponent={OnboardArea}
readOnly={false}>
<WorkbenchViewContribution
side="left"
title="Explorer"
icon={<AccountTreeIcon />}
component={ExplorerView}
/>
<WorkbenchViewContribution
side="left"
title="Validation"
icon={<WarningIcon />}
component={ValidationView}
/>
<WorkbenchViewContribution side="right" title="Details" icon={<MenuIcon />} component={DetailsView} />
<WorkbenchViewContribution
side="right"
title="Representations"
icon={<Filter />}
component={RepresentationsView}
/>
<WorkbenchViewContribution
side="right"
title="Related Elements"
icon={<LinkIcon />}
component={RelatedElementsView}
/>
</Workbench>
<DiagramPaletteToolContext.Provider value={diagramPaletteToolContributions}>
<Workbench
editingContextId={project.currentEditingContext.id}
initialRepresentationSelected={representation}
onRepresentationSelected={onRepresentationSelected}
mainAreaComponent={OnboardArea}
readOnly={false}>
<WorkbenchViewContribution
side="left"
title="Explorer"
icon={<AccountTreeIcon />}
component={ExplorerView}
/>
<WorkbenchViewContribution
side="left"
title="Validation"
icon={<WarningIcon />}
component={ValidationView}
/>
<WorkbenchViewContribution side="right" title="Details" icon={<MenuIcon />} component={DetailsView} />
<WorkbenchViewContribution
side="right"
title="Representations"
icon={<Filter />}
component={RepresentationsView}
/>
<WorkbenchViewContribution
side="right"
title="Related Elements"
icon={<LinkIcon />}
component={RelatedElementsView}
/>
</Workbench>
</DiagramPaletteToolContext.Provider>
</TreeToolBarContext.Provider>
</TreeItemContextMenuContext.Provider>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*******************************************************************************
* Copyright (c) 2023 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
*******************************************************************************/
import {
DiagramPaletteToolContributionComponentProps,
NodeData,
} from '@eclipse-sirius/sirius-components-diagrams-reactflow';
import Dialog from '@material-ui/core/Dialog';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import IconButton from '@material-ui/core/IconButton';
import { Slideshow } from '@material-ui/icons';
import { Fragment, useState } from 'react';
import { useNodes } from 'reactflow';

type Modal = 'dialog';
export const PapayaOperationActivityLabelDetailToolContribution = ({
diagramElementId,
}: DiagramPaletteToolContributionComponentProps) => {
const [modal, setModal] = useState<Modal | null>(null);

const nodes = useNodes<NodeData>();
const targetedNode = nodes.find((node) => node.id === diagramElementId);

const onClose = () => {
setModal(null);
};

let modalElement: JSX.Element | null = null;
if (modal === 'dialog' && targetedNode) {
modalElement = (
<>
<Dialog open={true} onClose={onClose} fullWidth>
<DialogContent>
<DialogContentText>{targetedNode.data.label.text}</DialogContentText>
</DialogContent>
</Dialog>
</>
);
}

return (
<Fragment key="label-detail-modal-contribution">
<IconButton
size="small"
color="inherit"
aria-label="Label detail"
title="Label detail"
onClick={() => setModal('dialog')}
data-testid="label-detail">
<Slideshow />
</IconButton>
{modalElement}
</Fragment>
);
};

0 comments on commit 1b57f6f

Please sign in to comment.