Skip to content

Commit

Permalink
[2804] Add the ability to declare custom nodes with the sirius-web-ap…
Browse files Browse the repository at this point in the history
…plication package

Bug: #2804
Signed-off-by: Axel RICHARD <axel.richard@obeo.fr>
  • Loading branch information
AxelRICHARD authored and sbegaudeau committed Dec 13, 2023
1 parent b203bcb commit 170b74c
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 60 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.adoc
Expand Up @@ -54,6 +54,18 @@ info: {
},
...
```
- https://github.com/eclipse-sirius/sirius-web/issues/2804[#2804] [sirius-web] Add the ability to declare custom nodes while using the `sirius-web-application` frontend package.
A new optional component named `DiagramRepresentationConfiguration` has been introduced.
If you want to add some custom nodes, this new component must be declared under `SiriusWebApplication`:
```ts
const nodeTypeRegistry: NodeTypeRegistry = {
...
};
<SiriusWebApplication httpOrigin={httpOrigin} wsOrigin={wsOrigin}>
<DiagramRepresentationConfiguration nodeTypeRegistry={nodeTypeRegistry} />
</SiriusWebApplication>
```


=== Dependency update

Expand Down Expand Up @@ -83,6 +95,7 @@ info: {
- https://github.com/eclipse-sirius/sirius-web/issues/2766[#2766] [tree] Tree representations (including the explorer) now support dragging any kind of element (not just semantic elements).
It is the responsibility of the drop targets (e.g. a diagram) to validate the dropped element(s) type and ignore the one it does not support.
- https://github.com/eclipse-sirius/sirius-web/issues/2772[#2772] Improve performance of the Palette
- https://github.com/eclipse-sirius/sirius-web/issues/2804[#2804] [sirius-web] Add the ability to declare custom nodes while using the `sirius-web-application` frontend package.


== v2023.12.0
Expand Down
Expand Up @@ -12,7 +12,7 @@
*******************************************************************************/

export { NodeTypeContext } from './contexts/NodeContext';
export type { NodeTypeContextValue } from './contexts/NodeContext.types';
export type { NodeTypeContextValue, NodeTypeContributionElement } from './contexts/NodeContext.types';
export type { IConvertEngine, INodeConverterHandler } from './converter/ConvertEngine.types';
export { convertLabelStyle, convertLineStyle } from './converter/convertDiagram';
export { AlignmentMap } from './converter/convertDiagram.types';
Expand Down
Expand Up @@ -12,12 +12,18 @@
*******************************************************************************/
import { ApolloProvider } from '@apollo/client';
import { ServerContext } from '@eclipse-sirius/sirius-components-core';
import { NodeTypeContext, NodeTypeContextValue } from '@eclipse-sirius/sirius-components-diagrams-reactflow';
import CssBaseline from '@material-ui/core/CssBaseline';
import { Theme, ThemeProvider } from '@material-ui/core/styles';
import React, { useMemo } from 'react';
import { BrowserRouter } from 'react-router-dom';
import { ToastProvider } from '../../src/toast/ToastProvider';
import { createApolloGraphQLClient } from '../ApolloGraphQLClient';
import {
DiagramRepresentationConfiguration,
defaultNodeTypeRegistry,
} from '../diagrams/DiagramRepresentationConfiguration';
import { DiagramRepresentationConfigurationProps } from '../diagrams/DiagramRepresentationConfiguration.types';
import { RepresentationContextProvider } from '../representations/RepresentationContextProvider';
import { Router } from '../router/Router';
import { siriusWebTheme as defaultTheme } from '../theme/siriusWebTheme';
Expand All @@ -40,6 +46,7 @@ export const SiriusWebApplication = ({ httpOrigin, wsOrigin, theme, children }:
const apolloClient = useMemo(() => createApolloGraphQLClient(httpOrigin, wsOrigin), [httpOrigin, wsOrigin]);

const value: ViewsContextValue = { ...defaultValue };
let nodeTypeRegistryValue: NodeTypeContextValue = { ...defaultNodeTypeRegistry };
React.Children.forEach(children, (child) => {
if (React.isValidElement(child) && child.type === Views) {
const { applicationIcon, applicationBarMenu } = child.props as ViewsProps;
Expand All @@ -49,6 +56,11 @@ export const SiriusWebApplication = ({ httpOrigin, wsOrigin, theme, children }:
if (applicationBarMenu) {
value.applicationBarMenu = applicationBarMenu;
}
} else if (React.isValidElement(child) && child.type === DiagramRepresentationConfiguration) {
const { nodeTypeRegistry } = child.props as DiagramRepresentationConfigurationProps;
if (nodeTypeRegistry) {
nodeTypeRegistryValue = nodeTypeRegistry;
}
}
});

Expand All @@ -60,11 +72,13 @@ export const SiriusWebApplication = ({ httpOrigin, wsOrigin, theme, children }:
<ServerContext.Provider value={{ httpOrigin }}>
<ToastProvider>
<RepresentationContextProvider>
<ViewsContext.Provider value={value}>
<div style={style}>
<Router />
</div>
</ViewsContext.Provider>
<NodeTypeContext.Provider value={nodeTypeRegistryValue}>
<ViewsContext.Provider value={value}>
<div style={style}>
<Router />
</div>
</ViewsContext.Provider>
</NodeTypeContext.Provider>
</RepresentationContextProvider>
</ToastProvider>
</ServerContext.Provider>
Expand Down
@@ -0,0 +1,26 @@
/*******************************************************************************
* 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 { NodeTypeContextValue } from '@eclipse-sirius/sirius-components-diagrams-reactflow';
import { DiagramRepresentationConfigurationProps } from './DiagramRepresentationConfiguration.types';

export const defaultNodeTypeRegistry: NodeTypeContextValue = {
nodeConverterHandlers: [],
nodeLayoutHandlers: [],
graphQLNodeStyleFragments: [],
nodeTypeContributions: [],
};

export const DiagramRepresentationConfiguration = ({}: DiagramRepresentationConfigurationProps) => {
return null;
};
@@ -0,0 +1,30 @@
/*******************************************************************************
* 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 {
GraphQLNodeStyleFragment,
INodeConverterHandler,
INodeLayoutHandler,
NodeData,
NodeTypeContributionElement,
} from '@eclipse-sirius/sirius-components-diagrams-reactflow';

export interface DiagramRepresentationConfigurationProps {
nodeTypeRegistry: NodeTypeRegistry;
}

export interface NodeTypeRegistry {
graphQLNodeStyleFragments: GraphQLNodeStyleFragment[];
nodeLayoutHandlers: INodeLayoutHandler<NodeData>[];
nodeConverterHandlers: INodeConverterHandler[];
nodeTypeContributions: NodeTypeContributionElement[];
}
Expand Up @@ -12,4 +12,5 @@
*******************************************************************************/

export { SiriusWebApplication } from './application/SiriusWebApplication';
export { DiagramRepresentationConfiguration } from './diagrams/DiagramRepresentationConfiguration';
export { Views } from './views/Views';
Expand Up @@ -17,9 +17,6 @@ import {
DiagramPaletteToolContextValue,
DiagramPaletteToolContribution,
NodeData,
NodeTypeContext,
NodeTypeContextValue,
NodeTypeContribution,
} from '@eclipse-sirius/sirius-components-diagrams-reactflow';
import { DetailsView, RelatedElementsView, RepresentationsView } from '@eclipse-sirius/sirius-components-forms';
import {
Expand All @@ -46,9 +43,6 @@ import { useEffect } from 'react';
import { generatePath, useHistory, useParams, useRouteMatch } from 'react-router-dom';
import { useNodes } from 'reactflow';
import { NavigationBar } from '../../navigationBar/NavigationBar';
import { EllipseNode } from '../../nodes/EllipseNode';
import { EllipseNodeConverterHandler } from '../../nodes/EllipseNodeConverterHandler';
import { EllipseNodeLayoutHandler } from '../../nodes/EllipseNodeLayoutHandler';
import { OnboardArea } from '../../onboarding/OnboardArea';
import { DiagramTreeItemContextMenuContribution } from './DiagramTreeItemContextMenuContribution';
import { DocumentTreeItemContextMenuContribution } from './DocumentTreeItemContextMenuContribution';
Expand Down Expand Up @@ -194,56 +188,42 @@ export const EditProjectView = () => {
/>,
];

const nodeTypeRegistryValue: NodeTypeContextValue = {
graphQLNodeStyleFragments: [
{
type: 'EllipseNodeStyle',
fields: `borderColor borderSize borderStyle color`,
},
],
nodeLayoutHandlers: [new EllipseNodeLayoutHandler()],
nodeConverterHandlers: [new EllipseNodeConverterHandler()],
nodeTypeContributions: [<NodeTypeContribution component={EllipseNode} type={'ellipseNode'} />],
};

main = (
<TreeItemContextMenuContext.Provider value={treeItemContextMenuContributions}>
<TreeToolBarContext.Provider value={treeToolBarContributions}>
<DiagramPaletteToolContext.Provider value={diagramPaletteToolContributions}>
<NodeTypeContext.Provider value={nodeTypeRegistryValue}>
<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>
</NodeTypeContext.Provider>
<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
26 changes: 24 additions & 2 deletions packages/sirius-web/frontend/sirius-web/src/index.tsx
Expand Up @@ -11,6 +11,7 @@
* Obeo - initial API and implementation
*******************************************************************************/
import { loadDevMessages, loadErrorMessages } from '@apollo/client/dev';
import { NodeTypeContribution } from '@eclipse-sirius/sirius-components-diagrams-reactflow';
import {
GQLWidget,
PropertySectionComponent,
Expand All @@ -25,10 +26,17 @@ import {
ReferencePreview,
ReferencePropertySection,
} from '@eclipse-sirius/sirius-components-widget-reference';
import { SiriusWebApplication } from '@eclipse-sirius/sirius-web-application';
import {
DiagramRepresentationConfiguration,
NodeTypeRegistry,
SiriusWebApplication,
} from '@eclipse-sirius/sirius-web-application';
import LinearScaleOutlinedIcon from '@material-ui/icons/LinearScaleOutlined';
import ReactDOM from 'react-dom';
import { httpOrigin, wsOrigin } from './core/URL';
import { EllipseNode } from './nodes/EllipseNode';
import { EllipseNodeConverterHandler } from './nodes/EllipseNodeConverterHandler';
import { EllipseNodeLayoutHandler } from './nodes/EllipseNodeLayoutHandler';
import { GQLSlider } from './widgets/SliderFragment.types';
import { SliderPreview } from './widgets/SliderPreview';
import { SliderPropertySection } from './widgets/SliderPropertySection';
Expand Down Expand Up @@ -106,9 +114,23 @@ const propertySectionRegistryValue: PropertySectionContextValue = {
propertySectionsRegistry,
};

const nodeTypeRegistry: NodeTypeRegistry = {
graphQLNodeStyleFragments: [
{
type: 'EllipseNodeStyle',
fields: `borderColor borderSize borderStyle color`,
},
],
nodeLayoutHandlers: [new EllipseNodeLayoutHandler()],
nodeConverterHandlers: [new EllipseNodeConverterHandler()],
nodeTypeContributions: [<NodeTypeContribution component={EllipseNode} type={'ellipseNode'} />],
};

ReactDOM.render(
<PropertySectionContext.Provider value={propertySectionRegistryValue}>
<SiriusWebApplication httpOrigin={httpOrigin} wsOrigin={wsOrigin} />
<SiriusWebApplication httpOrigin={httpOrigin} wsOrigin={wsOrigin}>
<DiagramRepresentationConfiguration nodeTypeRegistry={nodeTypeRegistry} />
</SiriusWebApplication>
</PropertySectionContext.Provider>,
document.getElementById('root')
);

0 comments on commit 170b74c

Please sign in to comment.