Skip to content

Commit

Permalink
[2343] Add icons on new object modals
Browse files Browse the repository at this point in the history
Bug: #2343
Signed-off-by: Florian ROUËNÉ <florian.rouene@obeosoft.com>
  • Loading branch information
frouene authored and sbegaudeau committed Sep 11, 2023
1 parent 1b57f6f commit b3afc08
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 19 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.adoc
Expand Up @@ -44,6 +44,7 @@ It's now possible to provide _referenceKind_ to only get the `ChildCreationDescr
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.
- https://github.com/eclipse-sirius/sirius-web/issues/2343[#2343] [sirius-web] Add iconURL field on `ChildCreationDescription` type.

=== Dependency update

Expand Down Expand Up @@ -105,6 +106,7 @@ To illustrate this new feature, we contribute a new tool on the _Papaya Diagram_
- https://github.com/eclipse-sirius/sirius-web/issues/2314[#2314] [diagram] Add feedback on edge selection on react-flow diagrams
- https://github.com/eclipse-sirius/sirius-web/issues/2313[#2313] [diagram] Support edge palette on react-flow diagrams
- https://github.com/eclipse-sirius/sirius-web/issues/2350[#2350] [form] Change the default tab width in form to fit the page label length.
- https://github.com/eclipse-sirius/sirius-web/issues/2343[#2343] [emf] Add icon for type selection in new object modal.

== v2023.8.0

Expand Down
Expand Up @@ -59,6 +59,7 @@ type StereotypeDescription {
type ChildCreationDescription {
id: ID!
label: String!
iconURL: String!
}

type EditingContextRepresentationConnection {
Expand Down
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2022 Obeo.
* Copyright (c) 2019, 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
Expand All @@ -21,13 +21,17 @@
* @author sbegaudeau
*/
public class ChildCreationDescription {

private final String id;

private final String label;

public ChildCreationDescription(String id, String label) {
private final String iconURL;

public ChildCreationDescription(String id, String label, String iconURL) {
this.id = Objects.requireNonNull(id);
this.label = Objects.requireNonNull(label);
this.iconURL = Objects.requireNonNull(iconURL);
}

public String getId() {
Expand All @@ -38,6 +42,10 @@ public String getLabel() {
return this.label;
}

public String getIconURL() {
return this.iconURL;
}

@Override
public String toString() {
String pattern = "{0} '{'id: {1}, label: {2}'}'";
Expand Down
Expand Up @@ -44,6 +44,7 @@
import org.eclipse.sirius.components.core.api.ChildCreationDescription;
import org.eclipse.sirius.components.core.api.IEditService;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.core.api.IObjectService;
import org.eclipse.sirius.components.emf.services.api.IEMFKindService;
import org.eclipse.sirius.emfjson.resource.JsonResourceImpl;
import org.springframework.stereotype.Service;
Expand All @@ -63,10 +64,13 @@ public class EditService implements IEditService {

private final ISuggestedRootObjectTypesProvider suggestedRootObjectTypesProvider;

public EditService(IEMFKindService emfKindService, ComposedAdapterFactory composedAdapterFactory, ISuggestedRootObjectTypesProvider suggestedRootObjectsProvider) {
private final IObjectService objectService;

public EditService(IEMFKindService emfKindService, ComposedAdapterFactory composedAdapterFactory, ISuggestedRootObjectTypesProvider suggestedRootObjectsProvider, IObjectService objectService) {
this.emfKindService = Objects.requireNonNull(emfKindService);
this.composedAdapterFactory = Objects.requireNonNull(composedAdapterFactory);
this.suggestedRootObjectTypesProvider = Objects.requireNonNull(suggestedRootObjectsProvider);
this.objectService = Objects.requireNonNull(objectService);
}

private Optional<EClass> getEClass(EPackage.Registry ePackageRegistry, String kind) {
Expand Down Expand Up @@ -131,7 +135,8 @@ public List<ChildCreationDescription> getChildCreationDescriptions(IEditingConte
if (editingDomainItemProvider instanceof Helper helper) {
for (CommandParameter commandParameter : commandParameters) {
String text = helper.getCreateChildText(eObject, commandParameter.getFeature(), commandParameter.getValue(), null);
ChildCreationDescription childCreationDescription = new ChildCreationDescription(text, text);
String iconURL = this.objectService.getImagePath(commandParameter.getValue());
ChildCreationDescription childCreationDescription = new ChildCreationDescription(text, text, iconURL);
childCreationDescriptions.add(childCreationDescription);
}
}
Expand Down Expand Up @@ -229,7 +234,8 @@ public List<ChildCreationDescription> getRootCreationDescriptions(IEditingContex
for (EClass suggestedClass : classes) {
if (referenceKind == null || this.getEClass(ePackageRegistry, referenceKind).map(eClassReference -> eClassReference.isSuperTypeOf(suggestedClass))
.orElse(true)) {
rootObjectCreationDescription.add(new ChildCreationDescription(suggestedClass.getName(), suggestedClass.getName()));
String iconURL = this.objectService.getImagePath(EcoreUtil.create(suggestedClass));
rootObjectCreationDescription.add(new ChildCreationDescription(suggestedClass.getName(), suggestedClass.getName(), iconURL));
}
}
}
Expand Down
Expand Up @@ -11,17 +11,19 @@
* Obeo - initial API and implementation
*******************************************************************************/
import { gql, useLazyQuery, useMutation } from '@apollo/client';
import { Selection, useMultiToast } from '@eclipse-sirius/sirius-components-core';
import { Selection, ServerContext, ServerContextValue, useMultiToast } from '@eclipse-sirius/sirius-components-core';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogTitle from '@material-ui/core/DialogTitle';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import MenuItem from '@material-ui/core/MenuItem';
import Select from '@material-ui/core/Select';
import { makeStyles } from '@material-ui/core/styles';
import { useMachine } from '@xstate/react';
import { useEffect } from 'react';
import { useContext, useEffect } from 'react';
import { ModelBrowserTreeView } from '../components/ModelBrowserTreeView';
import {
CreateModalProps,
Expand Down Expand Up @@ -59,6 +61,13 @@ const useStyle = makeStyles((theme) => ({
opacity: 0.6,
fontSize: theme.typography.caption.fontSize,
},
select: {
display: 'flex',
alignItems: 'center',
},
iconRoot: {
minWidth: theme.spacing(3),
},
}));

const createChildMutation = gql`
Expand Down Expand Up @@ -104,6 +113,7 @@ const getChildCreationDescriptionsQuery = gql`
childCreationDescriptions(kind: $kind, referenceKind: $referenceKind) {
id
label
iconURL
}
}
}
Expand All @@ -122,6 +132,7 @@ const getRootObjectCreationDescriptionsQuery = gql`
rootObjectCreationDescriptions(domainId: $domainId, suggested: $suggested, referenceKind: $referenceKind) {
id
label
iconURL
}
}
}
Expand All @@ -146,6 +157,7 @@ const isErrorPayload = (payload: GQLCreateChildPayload): payload is GQLErrorPayl

export const CreateModal = ({ editingContextId, widget, onClose }: CreateModalProps) => {
const classes = useStyle();
const { httpOrigin } = useContext<ServerContextValue>(ServerContext);
const { addErrorMessage } = useMultiToast();
const [{ value, context }, dispatch] = useMachine<CreateModalContext, CreateModalEvent>(createModalMachine);
const { createModal } = value as SchemaValue;
Expand Down Expand Up @@ -402,6 +414,7 @@ export const CreateModal = ({ editingContextId, widget, onClose }: CreateModalPr
)}
<span className={classes.title}>Select the object type</span>
<Select
classes={{ select: classes.select }}
value={selectedChildCreationDescriptionId}
onChange={onChildCreationDescriptionChange}
disabled={createModal !== 'validForChild' && createModal !== 'validForRoot'}
Expand All @@ -410,7 +423,17 @@ export const CreateModal = ({ editingContextId, widget, onClose }: CreateModalPr
data-testid="childCreationDescription">
{creationDescriptions.map((creationDescription) => (
<MenuItem value={creationDescription.id} key={creationDescription.id}>
{creationDescription.label}
{creationDescription.iconURL && (
<ListItemIcon className={classes.iconRoot}>
<img
height="16"
width="16"
alt={creationDescription.label}
src={httpOrigin + creationDescription.iconURL}
/>
</ListItemIcon>
)}
<ListItemText primary={creationDescription.label} />
</MenuItem>
))}
</Select>
Expand Down
Expand Up @@ -51,6 +51,7 @@ export interface GQLEditingContext {
export interface GQLChildCreationDescription {
id: string;
label: string;
iconURL: string;
}

export interface GQLCreateRootObjectMutationData {
Expand Down Expand Up @@ -92,6 +93,7 @@ export interface GQLRootEditingContext {
export interface GQLRootChildCreationDescription {
id: string;
label: string;
iconURL: string;
}

export interface GQLDomain {
Expand All @@ -117,6 +119,7 @@ export interface GQLCreateChildSuccessPayload extends GQLCreateChildPayload {
export interface ChildCreationDescription {
id: string;
label: string;
iconURL: string;
}

export interface GQLObject {
Expand Down
Expand Up @@ -35,6 +35,7 @@
* @generated
*/
public class SliderDescriptionItemProvider extends WidgetDescriptionItemProvider {

/**
* This constructs an instance from a factory and a notifier. <!-- begin-user-doc --> <!-- end-user-doc -->
*
Expand Down Expand Up @@ -147,11 +148,11 @@ protected EStructuralFeature getChildFeature(Object object, Object child) {
/**
* This returns SliderDescription.gif. <!-- begin-user-doc --> <!-- end-user-doc -->
*
* @generated
* @generated NOT
*/
@Override
public Object getImage(Object object) {
return this.overlayImage(object, this.getResourceLocator().getImage("full/obj16/SliderDescription"));
return this.overlayImage(object, this.getResourceLocator().getImage("full/obj16/SliderDescription.svg"));
}

/**
Expand Down
@@ -0,0 +1,35 @@
/*******************************************************************************
* 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
*******************************************************************************/
package org.eclipse.sirius.web.graphql.datafetchers;

import org.eclipse.sirius.components.annotations.spring.graphql.QueryDataFetcher;
import org.eclipse.sirius.components.core.api.ChildCreationDescription;
import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates;
import org.eclipse.sirius.components.graphql.api.URLConstants;

import graphql.schema.DataFetchingEnvironment;

/**
* The data fetcher used to concatenate the server image URL to the childCreationDescription icon image path.
*
* @author pcdavid
*/
@QueryDataFetcher(type = "ChildCreationDescription", field = "iconURL")
public class ChildCreationDescriptionIconURLDataFetcher implements IDataFetcherWithFieldCoordinates<String> {

@Override
public String get(DataFetchingEnvironment environment) throws Exception {
ChildCreationDescription childCreationDescription = environment.getSource();
return URLConstants.IMAGE_BASE_PATH + childCreationDescription.getIconURL();
}
}
Expand Up @@ -11,18 +11,20 @@
* Obeo - initial API and implementation
*******************************************************************************/
import { gql, useMutation, useQuery } from '@apollo/client';
import { Toast } from '@eclipse-sirius/sirius-components-core';
import { ServerContext, ServerContextValue, Toast } from '@eclipse-sirius/sirius-components-core';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogTitle from '@material-ui/core/DialogTitle';
import InputLabel from '@material-ui/core/InputLabel';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import MenuItem from '@material-ui/core/MenuItem';
import Select from '@material-ui/core/Select';
import { makeStyles } from '@material-ui/core/styles';
import { useMachine } from '@xstate/react';
import { useEffect } from 'react';
import { useContext, useEffect } from 'react';
import {
GQLCreateChildMutationData,
GQLCreateChildPayload,
Expand All @@ -39,9 +41,9 @@ import {
HideToastEvent,
NewObjectModalContext,
NewObjectModalEvent,
newObjectModalMachine,
SchemaValue,
ShowToastEvent,
newObjectModalMachine,
} from './NewObjectModalMachine';

const createChildMutation = gql`
Expand Down Expand Up @@ -69,6 +71,7 @@ const getChildCreationDescriptionsQuery = gql`
childCreationDescriptions(kind: $kind) {
id
label
iconURL
}
}
}
Expand All @@ -83,13 +86,21 @@ const useNewObjectModalStyles = makeStyles((theme) => ({
marginBottom: theme.spacing(1),
},
},
select: {
display: 'flex',
alignItems: 'center',
},
iconRoot: {
minWidth: theme.spacing(3),
},
}));

const isErrorPayload = (payload: GQLCreateChildPayload): payload is GQLErrorPayload =>
payload.__typename === 'ErrorPayload';

export const NewObjectModal = ({ editingContextId, item, onObjectCreated, onClose }: NewObjectModalProps) => {
const classes = useNewObjectModalStyles();
const { httpOrigin } = useContext<ServerContextValue>(ServerContext);
const [{ value, context }, dispatch] = useMachine<NewObjectModalContext, NewObjectModalEvent>(newObjectModalMachine);
const { newObjectModal, toast } = value as SchemaValue;
const { selectedChildCreationDescriptionId, childCreationDescriptions, objectToSelect, message } = context;
Expand Down Expand Up @@ -171,7 +182,6 @@ export const NewObjectModal = ({ editingContextId, item, onObjectCreated, onClos
onObjectCreated({ entries: [objectToSelect] });
}
}, [newObjectModal, onObjectCreated, objectToSelect]);

return (
<>
<Dialog open={true} onClose={onClose} aria-labelledby="dialog-title" maxWidth="xs" fullWidth>
Expand All @@ -180,6 +190,7 @@ export const NewObjectModal = ({ editingContextId, item, onObjectCreated, onClos
<div className={classes.form}>
<InputLabel id="newObjectModalChildCreationDescriptionLabel">Object type</InputLabel>
<Select
classes={{ select: classes.select }}
value={selectedChildCreationDescriptionId}
onChange={onChildCreationDescriptionChange}
disabled={newObjectModal === 'loading' || newObjectModal === 'creatingChild'}
Expand All @@ -188,7 +199,17 @@ export const NewObjectModal = ({ editingContextId, item, onObjectCreated, onClos
data-testid="childCreationDescription">
{childCreationDescriptions.map((childCreationDescription) => (
<MenuItem value={childCreationDescription.id} key={childCreationDescription.id}>
{childCreationDescription.label}
{childCreationDescription.iconURL && (
<ListItemIcon className={classes.iconRoot}>
<img
height="16"
width="16"
alt={childCreationDescription.label}
src={httpOrigin + childCreationDescription.iconURL}
/>
</ListItemIcon>
)}
<ListItemText primary={childCreationDescription.label} />
</MenuItem>
))}
</Select>
Expand Down
Expand Up @@ -23,6 +23,7 @@ export interface NewObjectModalProps {
export interface ChildCreationDescription {
id: string;
label: string;
iconURL: string;
}

export interface GQLGetChildCreationDescriptionsQueryVariables {
Expand All @@ -46,6 +47,7 @@ export interface GQLEditingContext {
export interface GQLChildCreationDescription {
id: string;
label: string;
iconURL: string;
}

export interface GQLCreateChildMutationData {
Expand Down

0 comments on commit b3afc08

Please sign in to comment.