Skip to content

Commit

Permalink
[3943] Add support for the widget refeference in the vs-code extension
Browse files Browse the repository at this point in the history
Bug: #3943
Signed-off-by: Michaël Charfadi <[email protected]>
  • Loading branch information
mcharfadi authored and sbegaudeau committed Sep 3, 2024
1 parent 147c54e commit fce12cb
Show file tree
Hide file tree
Showing 5 changed files with 325 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions vscode-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
39 changes: 22 additions & 17 deletions vscode-extension/src/view/app/index.tsx
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -79,23 +81,26 @@ const ApolloGraphQLClient = new ApolloClient({
link: splitLink,
cache: new InMemoryCache({ addTypename: true }),
defaultOptions,
documentTransform: referenceWidgetDocumentTransform,
});

ReactDOM.render(
<ServerContext.Provider value={value}>
<ApolloProvider client={ApolloGraphQLClient}>
<ToastProvider>
<App
serverAddress={window.serverAddress}
username={window.username}
password={window.password}
editingContextId={window.editingContextId}
representationId={window.representationId}
representationLabel={window.representationLabel}
representationKind={window.representationKind}
/>
</ToastProvider>
</ApolloProvider>
</ServerContext.Provider>,
<ExtensionProvider registry={defaultExtensionRegistry}>
<ServerContext.Provider value={value}>
<ApolloProvider client={ApolloGraphQLClient}>
<ToastProvider>
<App
serverAddress={window.serverAddress}
username={window.username}
password={window.password}
editingContextId={window.editingContextId}
representationId={window.representationId}
representationLabel={window.representationLabel}
representationKind={window.representationKind}
/>
</ToastProvider>
</ApolloProvider>
</ServerContext.Provider>
</ExtensionProvider>,
document.getElementById('root')
);
Original file line number Diff line number Diff line change
@@ -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: <ReferenceIcon />,
previewComponent: ReferencePreview,
component: (widget: GQLWidget): PropertySectionComponent<GQLWidget> | null => {
let propertySectionComponent: PropertySectionComponent<GQLWidget> | null = null;

if (isReferenceWidget(widget)) {
propertySectionComponent = ReferencePropertySection;
}
return propertySectionComponent;
},
},
],
});

export { defaultExtensionRegistry };
Original file line number Diff line number Diff line change
@@ -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;
});

0 comments on commit fce12cb

Please sign in to comment.