diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index 4f0360fe6f..374bbff312 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -1151,6 +1151,7 @@ An error message is now displayed if the _Shape_ is not set.
- https://github.com/eclipse-sirius/sirius-web/issues/2426[#2426] [sirius-web] Fix an issue where the Representations view was always empty.
- https://github.com/eclipse-sirius/sirius-web/issues/2429[#2429] [sirius-web] Ensure that view models can be successfully uploaded by loading the default color palettes
- https://github.com/eclipse-sirius/sirius-web/issues/2433[#2433] [form] Fix an issue where the readonly property of FlexboxContainerPropertySection was not correctly dispatched to children.
+- https://github.com/eclipse-sirius/sirius-web/issues/3943[#3943] [vs-code] Fix an issue with widget reference
=== New Features
diff --git a/vscode-extension/package.json b/vscode-extension/package.json
index 765c7dc231..07bebb1f49 100644
--- a/vscode-extension/package.json
+++ b/vscode-extension/package.json
@@ -135,6 +135,7 @@
"@eclipse-sirius/sirius-components-selection": "*",
"@eclipse-sirius/sirius-components-trees": "*",
"@eclipse-sirius/sirius-components-validation": "*",
+ "@eclipse-sirius/sirius-web-application": "*",
"@mui/icons-material": "5.15.19",
"@mui/material": "5.15.19",
"@ObeoNetwork/gantt-task-react": "0.5.0",
diff --git a/vscode-extension/src/view/app/index.tsx b/vscode-extension/src/view/app/index.tsx
index fe4bbec0d2..dfc191cc02 100644
--- a/vscode-extension/src/view/app/index.tsx
+++ b/vscode-extension/src/view/app/index.tsx
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2022, 2023 Obeo.
+ * Copyright (c) 2022, 2024 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
@@ -14,11 +14,13 @@
import { ApolloClient, ApolloProvider, DefaultOptions, HttpLink, InMemoryCache, split } from '@apollo/client';
import { WebSocketLink } from '@apollo/client/link/ws';
import { getMainDefinition } from '@apollo/client/utilities';
-import { ServerContext } from '@eclipse-sirius/sirius-components-core';
+import { ExtensionProvider, ServerContext } from '@eclipse-sirius/sirius-components-core';
import React from 'react';
import ReactDOM from 'react-dom';
import { App } from './App';
import './index.css';
+import { defaultExtensionRegistry } from './registry/DefaultExtensionRegistry';
+import { referenceWidgetDocumentTransform } from './registry/ReferenceWidgetDocumentTransform';
import { ToastProvider } from './toast/ToastProvider';
declare global {
@@ -79,23 +81,26 @@ const ApolloGraphQLClient = new ApolloClient({
link: splitLink,
cache: new InMemoryCache({ addTypename: true }),
defaultOptions,
+ documentTransform: referenceWidgetDocumentTransform,
});
ReactDOM.render(
-
-
-
-
-
-
- ,
+
+
+
+
+
+
+
+
+ ,
document.getElementById('root')
);
diff --git a/vscode-extension/src/view/app/registry/DefaultExtensionRegistry.tsx b/vscode-extension/src/view/app/registry/DefaultExtensionRegistry.tsx
new file mode 100644
index 0000000000..10ae8d7cae
--- /dev/null
+++ b/vscode-extension/src/view/app/registry/DefaultExtensionRegistry.tsx
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2024 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 { ExtensionRegistry } from '@eclipse-sirius/sirius-components-core';
+import {
+ GQLWidget,
+ PropertySectionComponent,
+ widgetContributionExtensionPoint,
+} from '@eclipse-sirius/sirius-components-forms';
+import {
+ GQLReferenceWidget,
+ ReferenceIcon,
+ ReferencePreview,
+ ReferencePropertySection,
+} from '@eclipse-sirius/sirius-components-widget-reference';
+import React from 'react';
+
+const defaultExtensionRegistry = new ExtensionRegistry();
+/*******************************************************************************
+ *
+ * Custom widget
+ *
+ * Used to register new custom widget in form
+ *
+ *******************************************************************************/
+
+const isReferenceWidget = (widget: GQLWidget): widget is GQLReferenceWidget => widget.__typename === 'ReferenceWidget';
+
+defaultExtensionRegistry.putData(widgetContributionExtensionPoint, {
+ identifier: `siriusWeb_${widgetContributionExtensionPoint.identifier}_referenceWidget`,
+ data: [
+ {
+ name: 'ReferenceWidget',
+ icon: ,
+ previewComponent: ReferencePreview,
+ component: (widget: GQLWidget): PropertySectionComponent | null => {
+ let propertySectionComponent: PropertySectionComponent | null = null;
+
+ if (isReferenceWidget(widget)) {
+ propertySectionComponent = ReferencePropertySection;
+ }
+ return propertySectionComponent;
+ },
+ },
+ ],
+});
+
+export { defaultExtensionRegistry };
diff --git a/vscode-extension/src/view/app/registry/ReferenceWidgetDocumentTransform.ts b/vscode-extension/src/view/app/registry/ReferenceWidgetDocumentTransform.ts
new file mode 100644
index 0000000000..d0cab0a13a
--- /dev/null
+++ b/vscode-extension/src/view/app/registry/ReferenceWidgetDocumentTransform.ts
@@ -0,0 +1,244 @@
+/*******************************************************************************
+ * Copyright (c) 2024 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 { DocumentTransform } from '@apollo/client';
+import { DocumentNode, FieldNode, FragmentSpreadNode, InlineFragmentNode, Kind, SelectionNode, visit } from 'graphql';
+
+const shouldTransform = (document: DocumentNode) => {
+ return (
+ document.definitions[0] &&
+ document.definitions[0].kind === Kind.OPERATION_DEFINITION &&
+ (document.definitions[0].name?.value === 'detailsEvent' || document.definitions[0].name?.value === 'formEvent')
+ );
+};
+
+const isWidgetFragment = (field: FieldNode) => {
+ if (field.selectionSet && (field.name.value === 'widgets' || field.name.value === 'children')) {
+ const fragmentSpreads = field.selectionSet.selections
+ .filter((selection: SelectionNode): selection is FragmentSpreadNode => selection.kind === Kind.FRAGMENT_SPREAD)
+ .map((fragmentSpread: FragmentSpreadNode) => fragmentSpread.name.value);
+ if (fragmentSpreads.includes('widgetFields')) {
+ return true;
+ }
+ }
+ return false;
+};
+
+const labelField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'label',
+ },
+};
+
+const iconURLField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'iconURL',
+ },
+};
+
+const ownerIdField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'ownerId',
+ },
+};
+
+const descriptionIdField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'descriptionId',
+ },
+};
+
+const ownerKindField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'ownerKind',
+ },
+};
+
+const referenceKindField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'referenceKind',
+ },
+};
+
+const containmentField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'containment',
+ },
+};
+
+const manyValuedField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'manyValued',
+ },
+};
+
+const referenceField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'reference',
+ },
+ selectionSet: {
+ kind: Kind.SELECTION_SET,
+ selections: [ownerKindField, referenceKindField, containmentField, manyValuedField],
+ },
+};
+
+const idField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'id',
+ },
+};
+
+const kindField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'kind',
+ },
+};
+
+const colorField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'color',
+ },
+};
+
+const fontSizeField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'fontSize',
+ },
+};
+
+const italicField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'italic',
+ },
+};
+
+const boldField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'bold',
+ },
+};
+
+const underlineField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'underline',
+ },
+};
+
+const strikeThroughField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'strikeThrough',
+ },
+};
+
+const referenceValuesField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'referenceValues',
+ },
+ selectionSet: {
+ kind: Kind.SELECTION_SET,
+ selections: [idField, labelField, kindField, iconURLField],
+ },
+};
+
+const styleField: SelectionNode = {
+ kind: Kind.FIELD,
+ name: {
+ kind: Kind.NAME,
+ value: 'style',
+ },
+ selectionSet: {
+ kind: Kind.SELECTION_SET,
+ selections: [colorField, fontSizeField, italicField, boldField, underlineField, strikeThroughField],
+ },
+};
+
+export const referenceWidgetDocumentTransform = new DocumentTransform((document) => {
+ if (shouldTransform(document)) {
+ return visit(document, {
+ Field(field) {
+ if (!isWidgetFragment(field)) {
+ return undefined;
+ }
+ const selections = field.selectionSet?.selections ?? [];
+
+ const referenceWidgetInlineFragment: InlineFragmentNode = {
+ kind: Kind.INLINE_FRAGMENT,
+ selectionSet: {
+ kind: Kind.SELECTION_SET,
+ selections: [
+ labelField,
+ iconURLField,
+ ownerIdField,
+ descriptionIdField,
+ referenceField,
+ referenceValuesField,
+ styleField,
+ ],
+ },
+ typeCondition: {
+ kind: Kind.NAMED_TYPE,
+ name: {
+ kind: Kind.NAME,
+ value: 'ReferenceWidget',
+ },
+ },
+ };
+
+ return {
+ ...field,
+ selectionSet: {
+ ...field.selectionSet,
+ selections: [...selections, referenceWidgetInlineFragment],
+ },
+ };
+ },
+ });
+ }
+ return document;
+});