From 8e52da3fdf5a027c68e121b4198cdf89a6b1ba26 Mon Sep 17 00:00:00 2001 From: Pierre-Charles David Date: Fri, 28 Oct 2022 11:34:21 +0200 Subject: [PATCH] [1439] Add support for toolbar actions on groups Bug: https://github.com/eclipse-sirius/sirius-components/issues/1439 Signed-off-by: Pierre-Charles David Signed-off-by: Axel RICHARD --- .../dto/AddToolbarActionInput.java | 71 ++++++ .../dto/AddToolbarActionSuccessPayload.java | 44 ++++ .../dto/DeleteToolbarActionInput.java | 71 ++++++ .../DeleteToolbarActionSuccessPayload.java | 44 ++++ .../dto/MoveToolbarActionInput.java | 85 +++++++ .../dto/MoveToolbarActionSuccessPayload.java | 44 ++++ .../AddToolbarActionEventHandler.java | 113 +++++++++ .../DeleteToolbarActionEventHandler.java | 101 ++++++++ .../MoveToolbarActionEventHandler.java | 127 ++++++++++ .../schema/formdescriptioneditor.graphqls | 51 ++++ ...mDescriptionEditorEventProcessorTests.java | 1 + .../TestFormDescriptionEditorBuilder.java | 1 + .../AddToolbarActionEventHandlerTests.java | 73 ++++++ .../DeleteToolbarActionEventHandlerTests.java | 98 ++++++++ .../MoveToolbarActionEventHandlerTests.java | 104 ++++++++ ...ormDescriptionEditorEventHandlerTests.java | 1 + .../MutationAddToolbarActionDataFetcher.java | 58 +++++ ...utationDeleteToolbarActionDataFetcher.java | 58 +++++ .../MutationMoveToolbarActionDataFetcher.java | 58 +++++ .../FormDescriptionEditor.java | 15 ++ .../FormDescriptionEditorToolbarAction.java | 77 ++++++ .../FormDescriptionEditorComponent.java | 20 ++ ...scriptionEditorToolbarActionComponent.java | 52 ++++ ...tionEditorToolbarActionComponentProps.java | 36 +++ ...riptionEditorToolbarActionDescription.java | 92 +++++++ ...iptionEditorToolbarActionElementProps.java | 105 ++++++++ ...criptionEditorComponentPropsValidator.java | 8 +- .../FormDescriptionEditorElementFactory.java | 20 ++ ...scriptionEditorInstancePropsValidator.java | 3 + .../src/ButtonWidget.tsx | 2 +- .../src/FlexboxContainerWidget.tsx | 2 + .../src/FormDescriptionEditorEventFragment.ts | 47 ++++ ...ormDescriptionEditorEventFragment.types.ts | 82 ++++++- .../FormDescriptionEditorRepresentation.tsx | 29 ++- .../src/ToolbarActionWidget.tsx | 226 ++++++++++++++++++ .../src/ToolbarActionWidget.types.ts | 28 +++ .../src/ToolbarActions.tsx | 205 ++++++++++++++++ .../src/ToolbarActions.types.ts | 22 ++ .../src/WidgetEntry.tsx | 5 +- .../src/WidgetEntry.types.ts | 3 + .../src/__tests__/WidgetEntry.test.tsx | 4 + .../collaborative/forms/FormQueryService.java | 3 +- .../src/main/resources/schema/form.graphqls | 1 + .../form/ButtonImageURLDataFetcher.java | 12 +- .../sirius/components/forms/Group.java | 18 +- .../components/forms/GroupContents.java | 75 ++++++ .../sirius/components/forms/GroupToolbar.java | 75 ++++++ .../forms/components/GroupComponent.java | 17 +- .../components/GroupContentsComponent.java | 39 +++ .../components/GroupToolbarComponent.java | 39 +++ .../forms/description/GroupDescription.java | 14 ++ .../renderer/FormComponentPropsValidator.java | 7 + .../forms/renderer/FormElementFactory.java | 49 +++- .../renderer/FormInstancePropsValidator.java | 7 + .../src/form/FormEventFragments.ts | 3 + .../src/form/FormEventFragments.types.ts | 1 + .../src/groups/Group.tsx | 50 +++- .../src/toolbaraction/ToolbarAction.tsx | 218 +++++++++++++++++ .../src/toolbaraction/ToolbarAction.types.ts | 78 ++++++ .../provider/FormDescriptionItemProvider.java | 27 +++ .../src/main/resources/plugin.properties | 1 + .../form/ViewFormDescriptionConverter.java | 8 + .../components/view/FormDescription.java | 11 + .../sirius/components/view/ViewPackage.java | 33 ++- .../view/impl/FormDescriptionImpl.java | 37 +++ .../components/view/impl/ViewPackageImpl.java | 15 +- .../src/main/resources/model/view.ecore | 2 + .../src/main/resources/model/view.genmodel | 1 + 68 files changed, 3097 insertions(+), 30 deletions(-) create mode 100644 packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/AddToolbarActionInput.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/AddToolbarActionSuccessPayload.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/DeleteToolbarActionInput.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/DeleteToolbarActionSuccessPayload.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/MoveToolbarActionInput.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/MoveToolbarActionSuccessPayload.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/AddToolbarActionEventHandler.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/DeleteToolbarActionEventHandler.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/MoveToolbarActionEventHandler.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/AddToolbarActionEventHandlerTests.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/DeleteToolbarActionEventHandlerTests.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/MoveToolbarActionEventHandlerTests.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors-graphql/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/graphql/datafetchers/mutation/MutationAddToolbarActionDataFetcher.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors-graphql/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/graphql/datafetchers/mutation/MutationDeleteToolbarActionDataFetcher.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors-graphql/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/graphql/datafetchers/mutation/MutationMoveToolbarActionDataFetcher.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/FormDescriptionEditorToolbarAction.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/components/FormDescriptionEditorToolbarActionComponent.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/components/FormDescriptionEditorToolbarActionComponentProps.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/description/FormDescriptionEditorToolbarActionDescription.java create mode 100644 packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/elements/FormDescriptionEditorToolbarActionElementProps.java create mode 100644 packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ToolbarActionWidget.tsx create mode 100644 packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ToolbarActionWidget.types.ts create mode 100644 packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ToolbarActions.tsx create mode 100644 packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ToolbarActions.types.ts create mode 100644 packages/forms/backend/sirius-components-forms/src/main/java/org/eclipse/sirius/components/forms/GroupContents.java create mode 100644 packages/forms/backend/sirius-components-forms/src/main/java/org/eclipse/sirius/components/forms/GroupToolbar.java create mode 100644 packages/forms/backend/sirius-components-forms/src/main/java/org/eclipse/sirius/components/forms/components/GroupContentsComponent.java create mode 100644 packages/forms/backend/sirius-components-forms/src/main/java/org/eclipse/sirius/components/forms/components/GroupToolbarComponent.java create mode 100644 packages/forms/frontend/sirius-components-forms/src/toolbaraction/ToolbarAction.tsx create mode 100644 packages/forms/frontend/sirius-components-forms/src/toolbaraction/ToolbarAction.types.ts diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/AddToolbarActionInput.java b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/AddToolbarActionInput.java new file mode 100644 index 0000000000..e8953b4e8d --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/AddToolbarActionInput.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.collaborative.formdescriptioneditors.dto; + +import java.text.MessageFormat; +import java.util.Objects; +import java.util.UUID; + +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.api.IFormDescriptionEditorInput; + +/** + * The input for the Form Description Editor add toolbar action mutation. + * + * @author arichard + */ +public class AddToolbarActionInput implements IFormDescriptionEditorInput { + + private UUID id; + + private String editingContextId; + + private String representationId; + + private String containerId; + + public AddToolbarActionInput() { + // Used by jackson + } + + public AddToolbarActionInput(UUID id, String editingContextId, String representationId, String containerId) { + this.id = Objects.requireNonNull(id); + this.editingContextId = Objects.requireNonNull(editingContextId); + this.representationId = Objects.requireNonNull(representationId); + this.containerId = containerId; + } + + @Override + public UUID getId() { + return this.id; + } + + @Override + public String getRepresentationId() { + return this.representationId; + } + + public String getEditingContextId() { + return this.editingContextId; + } + + public String getContainerId() { + return this.containerId; + } + + @Override + public String toString() { + String pattern = "{0} '{'id: {1}, editingContextId: {2}, representationId: {3}, containerId: {4}}'"; //$NON-NLS-1$ + return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.id, this.editingContextId, this.representationId, this.containerId); + } + +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/AddToolbarActionSuccessPayload.java b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/AddToolbarActionSuccessPayload.java new file mode 100644 index 0000000000..4bfb9c7cd0 --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/AddToolbarActionSuccessPayload.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.collaborative.formdescriptioneditors.dto; + +import java.text.MessageFormat; +import java.util.Objects; +import java.util.UUID; + +import org.eclipse.sirius.components.core.api.IPayload; + +/** + * The payload of the Form Description Editor add toolbar action mutation. + * + * @author arichard + */ +public class AddToolbarActionSuccessPayload implements IPayload { + private final UUID id; + + public AddToolbarActionSuccessPayload(UUID id) { + this.id = Objects.requireNonNull(id); + } + + @Override + public UUID getId() { + return this.id; + } + + @Override + public String toString() { + String pattern = "{0} '{'id: {1}'}'"; //$NON-NLS-1$ + return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.id); + } + +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/DeleteToolbarActionInput.java b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/DeleteToolbarActionInput.java new file mode 100644 index 0000000000..481d960682 --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/DeleteToolbarActionInput.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.collaborative.formdescriptioneditors.dto; + +import java.text.MessageFormat; +import java.util.Objects; +import java.util.UUID; + +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.api.IFormDescriptionEditorInput; + +/** + * The input for the Form Description Editor delete toolbar action mutation. + * + * @author arichard + */ +public class DeleteToolbarActionInput implements IFormDescriptionEditorInput { + + private UUID id; + + private String editingContextId; + + private String representationId; + + private String toolbarActionId; + + public DeleteToolbarActionInput() { + // Used by jackson + } + + public DeleteToolbarActionInput(UUID id, String editingContextId, String representationId, String toolbarActionId) { + this.id = Objects.requireNonNull(id); + this.editingContextId = Objects.requireNonNull(editingContextId); + this.representationId = Objects.requireNonNull(representationId); + this.toolbarActionId = Objects.requireNonNull(toolbarActionId); + } + + @Override + public UUID getId() { + return this.id; + } + + @Override + public String getRepresentationId() { + return this.representationId; + } + + public String getEditingContextId() { + return this.editingContextId; + } + + public String getToolbarActionId() { + return this.toolbarActionId; + } + + @Override + public String toString() { + String pattern = "{0} '{'id: {1}, editingContextId: {2}, representationId: {3}; toolbarActionId: {4}}'"; //$NON-NLS-1$ + return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.id, this.editingContextId, this.representationId, this.toolbarActionId); + } + +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/DeleteToolbarActionSuccessPayload.java b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/DeleteToolbarActionSuccessPayload.java new file mode 100644 index 0000000000..466acf0160 --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/DeleteToolbarActionSuccessPayload.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.collaborative.formdescriptioneditors.dto; + +import java.text.MessageFormat; +import java.util.Objects; +import java.util.UUID; + +import org.eclipse.sirius.components.core.api.IPayload; + +/** + * The payload of the Form Description Editor delete toolbar action mutation. + * + * @author arichard + */ +public class DeleteToolbarActionSuccessPayload implements IPayload { + private final UUID id; + + public DeleteToolbarActionSuccessPayload(UUID id) { + this.id = Objects.requireNonNull(id); + } + + @Override + public UUID getId() { + return this.id; + } + + @Override + public String toString() { + String pattern = "{0} '{'id: {1}'}'"; //$NON-NLS-1$ + return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.id); + } + +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/MoveToolbarActionInput.java b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/MoveToolbarActionInput.java new file mode 100644 index 0000000000..c3a34de452 --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/MoveToolbarActionInput.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.collaborative.formdescriptioneditors.dto; + +import java.text.MessageFormat; +import java.util.Objects; +import java.util.UUID; + +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.api.IFormDescriptionEditorInput; + +/** + * The input for the Form Description Editor add toolbar action mutation. + * + * @author arichard + */ +public class MoveToolbarActionInput implements IFormDescriptionEditorInput { + + private UUID id; + + private String editingContextId; + + private String representationId; + + private String containerId; + + private String toolbarActionId; + + private int index; + + public MoveToolbarActionInput() { + // Used by jackson + } + + public MoveToolbarActionInput(UUID id, String editingContextId, String representationId, String containerId, String toolbarActionId, int index) { + this.id = Objects.requireNonNull(id); + this.editingContextId = Objects.requireNonNull(editingContextId); + this.representationId = Objects.requireNonNull(representationId); + this.containerId = containerId; + this.toolbarActionId = Objects.requireNonNull(toolbarActionId); + this.index = Objects.requireNonNull(index); + } + + @Override + public UUID getId() { + return this.id; + } + + @Override + public String getRepresentationId() { + return this.representationId; + } + + public String getEditingContextId() { + return this.editingContextId; + } + + public String getContainerId() { + return this.containerId; + } + + public String getToolbarActionId() { + return this.toolbarActionId; + } + + public int getIndex() { + return this.index; + } + + @Override + public String toString() { + String pattern = "{0} '{'id: {1}, editingContextId: {2}, representationId: {3}, containerId: {4}, toolbarActionId: {5}, index: {6}}'"; //$NON-NLS-1$ + return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.id, this.editingContextId, this.representationId, this.containerId, this.toolbarActionId, this.index); + } + +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/MoveToolbarActionSuccessPayload.java b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/MoveToolbarActionSuccessPayload.java new file mode 100644 index 0000000000..801ffd42f1 --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/dto/MoveToolbarActionSuccessPayload.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.collaborative.formdescriptioneditors.dto; + +import java.text.MessageFormat; +import java.util.Objects; +import java.util.UUID; + +import org.eclipse.sirius.components.core.api.IPayload; + +/** + * The payload of the Form Description Editor move toolbar action mutation. + * + * @author arichard + */ +public class MoveToolbarActionSuccessPayload implements IPayload { + private final UUID id; + + public MoveToolbarActionSuccessPayload(UUID id) { + this.id = Objects.requireNonNull(id); + } + + @Override + public UUID getId() { + return this.id; + } + + @Override + public String toString() { + String pattern = "{0} '{'id: {1}'}'"; //$NON-NLS-1$ + return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.id); + } + +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/AddToolbarActionEventHandler.java b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/AddToolbarActionEventHandler.java new file mode 100644 index 0000000000..b1b6512a0f --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/AddToolbarActionEventHandler.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.collaborative.formdescriptioneditors.handlers; + +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.sirius.components.collaborative.api.ChangeDescription; +import org.eclipse.sirius.components.collaborative.api.ChangeKind; +import org.eclipse.sirius.components.collaborative.api.Monitoring; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.api.IFormDescriptionEditorContext; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.api.IFormDescriptionEditorEventHandler; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.api.IFormDescriptionEditorInput; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.dto.AddToolbarActionInput; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.dto.AddToolbarActionSuccessPayload; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.messages.ICollaborativeFormDescriptionEditorMessageService; +import org.eclipse.sirius.components.core.api.ErrorPayload; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IObjectService; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.view.FormDescription; +import org.eclipse.sirius.components.view.ViewFactory; +import org.springframework.stereotype.Service; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.MeterRegistry; +import reactor.core.publisher.Sinks.Many; +import reactor.core.publisher.Sinks.One; + +/** + * Handle the add toolbarAction event on Form Description Editor. + * + * @author arichard + */ +@Service +public class AddToolbarActionEventHandler implements IFormDescriptionEditorEventHandler { + + private final IObjectService objectService; + + private final ICollaborativeFormDescriptionEditorMessageService messageService; + + private final Counter counter; + + public AddToolbarActionEventHandler(IObjectService objectService, ICollaborativeFormDescriptionEditorMessageService messageService, MeterRegistry meterRegistry) { + this.objectService = Objects.requireNonNull(objectService); + this.messageService = Objects.requireNonNull(messageService); + + // @formatter:off + this.counter = Counter.builder(Monitoring.EVENT_HANDLER) + .tag(Monitoring.NAME, this.getClass().getSimpleName()) + .register(meterRegistry); + // @formatter:on + } + + @Override + public boolean canHandle(IFormDescriptionEditorInput formDescriptionEditorInput) { + return formDescriptionEditorInput instanceof AddToolbarActionInput; + } + + @Override + public void handle(One payloadSink, Many changeDescriptionSink, IEditingContext editingContext, IFormDescriptionEditorContext formDescriptionEditorContext, + IFormDescriptionEditorInput formDescriptionEditorInput) { + this.counter.increment(); + + String message = this.messageService.invalidInput(formDescriptionEditorInput.getClass().getSimpleName(), AddToolbarActionInput.class.getSimpleName()); + IPayload payload = new ErrorPayload(formDescriptionEditorInput.getId(), message); + ChangeDescription changeDescription = new ChangeDescription(ChangeKind.NOTHING, formDescriptionEditorInput.getRepresentationId(), formDescriptionEditorInput); + + if (formDescriptionEditorInput instanceof AddToolbarActionInput) { + String containerId = ((AddToolbarActionInput) formDescriptionEditorInput).getContainerId(); + boolean addToolbarAction = this.addToolbarAction(editingContext, formDescriptionEditorContext, containerId); + if (addToolbarAction) { + payload = new AddToolbarActionSuccessPayload(formDescriptionEditorInput.getId()); + changeDescription = new ChangeDescription(ChangeKind.SEMANTIC_CHANGE, formDescriptionEditorInput.getRepresentationId(), formDescriptionEditorInput); + } + } + + payloadSink.tryEmitValue(payload); + changeDescriptionSink.tryEmitNext(changeDescription); + } + + private boolean addToolbarAction(IEditingContext editingContext, IFormDescriptionEditorContext formDescriptionEditorContext, String containerId) { + boolean success = false; + var optionalSelf = Optional.empty(); + if (containerId != null) { + optionalSelf = this.objectService.getObject(editingContext, containerId); + } else { + optionalSelf = this.objectService.getObject(editingContext, formDescriptionEditorContext.getFormDescriptionEditor().getTargetObjectId()); + } + if (optionalSelf.isPresent()) { + Object container = optionalSelf.get(); + if (container instanceof FormDescription) { + var toolbarActionDescription = ViewFactory.eINSTANCE.createButtonDescription(); + toolbarActionDescription.setName("ToolbarAction"); //$NON-NLS-1$ + var toolbarActionDescriptionStyle = ViewFactory.eINSTANCE.createButtonDescriptionStyle(); + toolbarActionDescription.setStyle(toolbarActionDescriptionStyle); + ((FormDescription) container).getToolbarActions().add(toolbarActionDescription); + success = true; + } + } + return success; + } +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/DeleteToolbarActionEventHandler.java b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/DeleteToolbarActionEventHandler.java new file mode 100644 index 0000000000..5777c0b7e7 --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/DeleteToolbarActionEventHandler.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.collaborative.formdescriptioneditors.handlers; + +import java.util.Objects; + +import org.eclipse.sirius.components.collaborative.api.ChangeDescription; +import org.eclipse.sirius.components.collaborative.api.ChangeKind; +import org.eclipse.sirius.components.collaborative.api.Monitoring; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.api.IFormDescriptionEditorContext; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.api.IFormDescriptionEditorEventHandler; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.api.IFormDescriptionEditorInput; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.dto.DeleteToolbarActionInput; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.dto.DeleteToolbarActionSuccessPayload; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.messages.ICollaborativeFormDescriptionEditorMessageService; +import org.eclipse.sirius.components.core.api.ErrorPayload; +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.core.api.IPayload; +import org.springframework.stereotype.Service; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.MeterRegistry; +import reactor.core.publisher.Sinks.Many; +import reactor.core.publisher.Sinks.One; + +/** + * Handle the delete toolbarAction event on Form Description Editor. + * + * @author arichard + */ +@Service +public class DeleteToolbarActionEventHandler implements IFormDescriptionEditorEventHandler { + + private final IObjectService objectService; + + private final IEditService editService; + + private final ICollaborativeFormDescriptionEditorMessageService messageService; + + private final Counter counter; + + public DeleteToolbarActionEventHandler(IObjectService objectService, IEditService editService, ICollaborativeFormDescriptionEditorMessageService messageService, MeterRegistry meterRegistry) { + this.objectService = Objects.requireNonNull(objectService); + this.editService = Objects.requireNonNull(editService); + this.messageService = Objects.requireNonNull(messageService); + + // @formatter:off + this.counter = Counter.builder(Monitoring.EVENT_HANDLER) + .tag(Monitoring.NAME, this.getClass().getSimpleName()) + .register(meterRegistry); + // @formatter:on + } + + @Override + public boolean canHandle(IFormDescriptionEditorInput formDescriptionEditorInput) { + return formDescriptionEditorInput instanceof DeleteToolbarActionInput; + } + + @Override + public void handle(One payloadSink, Many changeDescriptionSink, IEditingContext editingContext, IFormDescriptionEditorContext formDescriptionEditorContext, + IFormDescriptionEditorInput formDescriptionEditorInput) { + this.counter.increment(); + + String message = this.messageService.invalidInput(formDescriptionEditorInput.getClass().getSimpleName(), DeleteToolbarActionInput.class.getSimpleName()); + IPayload payload = new ErrorPayload(formDescriptionEditorInput.getId(), message); + ChangeDescription changeDescription = new ChangeDescription(ChangeKind.NOTHING, formDescriptionEditorInput.getRepresentationId(), formDescriptionEditorInput); + + if (formDescriptionEditorInput instanceof DeleteToolbarActionInput) { + String toolbarActionId = ((DeleteToolbarActionInput) formDescriptionEditorInput).getToolbarActionId(); + boolean deleteToolbarAction = this.deleteToolbarAction(editingContext, formDescriptionEditorContext, toolbarActionId); + if (deleteToolbarAction) { + payload = new DeleteToolbarActionSuccessPayload(formDescriptionEditorInput.getId()); + changeDescription = new ChangeDescription(ChangeKind.SEMANTIC_CHANGE, formDescriptionEditorInput.getRepresentationId(), formDescriptionEditorInput); + } + } + + payloadSink.tryEmitValue(payload); + changeDescriptionSink.tryEmitNext(changeDescription); + } + + protected boolean deleteToolbarAction(IEditingContext editingContext, IFormDescriptionEditorContext formDescriptionEditorContext, String toolbarActionId) { + var optionalSelf = this.objectService.getObject(editingContext, toolbarActionId); + if (optionalSelf.isPresent()) { + this.editService.delete(optionalSelf.get()); + return true; + } + return false; + } +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/MoveToolbarActionEventHandler.java b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/MoveToolbarActionEventHandler.java new file mode 100644 index 0000000000..7b3dd157a6 --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/MoveToolbarActionEventHandler.java @@ -0,0 +1,127 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.collaborative.formdescriptioneditors.handlers; + +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.sirius.components.collaborative.api.ChangeDescription; +import org.eclipse.sirius.components.collaborative.api.ChangeKind; +import org.eclipse.sirius.components.collaborative.api.Monitoring; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.api.IFormDescriptionEditorContext; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.api.IFormDescriptionEditorEventHandler; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.api.IFormDescriptionEditorInput; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.dto.MoveToolbarActionInput; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.dto.MoveToolbarActionSuccessPayload; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.messages.ICollaborativeFormDescriptionEditorMessageService; +import org.eclipse.sirius.components.core.api.ErrorPayload; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IObjectService; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.view.ButtonDescription; +import org.eclipse.sirius.components.view.FormDescription; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.MeterRegistry; +import reactor.core.publisher.Sinks.Many; +import reactor.core.publisher.Sinks.One; + +/** + * Handle the move toolbar action event on Form Description Editor. + * + * @author arichard + */ +@Service +public class MoveToolbarActionEventHandler implements IFormDescriptionEditorEventHandler { + + private final Logger logger = LoggerFactory.getLogger(MoveToolbarActionEventHandler.class); + + private final IObjectService objectService; + + private final ICollaborativeFormDescriptionEditorMessageService messageService; + + private final Counter counter; + + public MoveToolbarActionEventHandler(IObjectService objectService, ICollaborativeFormDescriptionEditorMessageService messageService, MeterRegistry meterRegistry) { + this.objectService = Objects.requireNonNull(objectService); + this.messageService = Objects.requireNonNull(messageService); + + // @formatter:off + this.counter = Counter.builder(Monitoring.EVENT_HANDLER) + .tag(Monitoring.NAME, this.getClass().getSimpleName()) + .register(meterRegistry); + // @formatter:on + } + + @Override + public boolean canHandle(IFormDescriptionEditorInput formDescriptionEditorInput) { + return formDescriptionEditorInput instanceof MoveToolbarActionInput; + } + + @Override + public void handle(One payloadSink, Many changeDescriptionSink, IEditingContext editingContext, IFormDescriptionEditorContext formDescriptionEditorContext, + IFormDescriptionEditorInput formDescriptionEditorInput) { + this.counter.increment(); + + String message = this.messageService.invalidInput(formDescriptionEditorInput.getClass().getSimpleName(), MoveToolbarActionInput.class.getSimpleName()); + IPayload payload = new ErrorPayload(formDescriptionEditorInput.getId(), message); + ChangeDescription changeDescription = new ChangeDescription(ChangeKind.NOTHING, formDescriptionEditorInput.getRepresentationId(), formDescriptionEditorInput); + + if (formDescriptionEditorInput instanceof MoveToolbarActionInput) { + String containerId = ((MoveToolbarActionInput) formDescriptionEditorInput).getContainerId(); + String toolbarActionId = ((MoveToolbarActionInput) formDescriptionEditorInput).getToolbarActionId(); + int index = ((MoveToolbarActionInput) formDescriptionEditorInput).getIndex(); + boolean moveToolbarAction = this.moveToolbarAction(editingContext, formDescriptionEditorContext, containerId, toolbarActionId, index); + if (moveToolbarAction) { + payload = new MoveToolbarActionSuccessPayload(formDescriptionEditorInput.getId()); + changeDescription = new ChangeDescription(ChangeKind.SEMANTIC_CHANGE, formDescriptionEditorInput.getRepresentationId(), formDescriptionEditorInput); + } + } + + payloadSink.tryEmitValue(payload); + changeDescriptionSink.tryEmitNext(changeDescription); + } + + private boolean moveToolbarAction(IEditingContext editingContext, IFormDescriptionEditorContext formDescriptionEditorContext, String containerId, String toolbarActionId, int index) { + boolean success = false; + var optionalSelf = Optional.empty(); + if (containerId != null) { + optionalSelf = this.objectService.getObject(editingContext, containerId); + } else { + optionalSelf = this.objectService.getObject(editingContext, formDescriptionEditorContext.getFormDescriptionEditor().getTargetObjectId()); + } + if (optionalSelf.isPresent()) { + Object container = optionalSelf.get(); + var objectToMove = this.objectService.getObject(editingContext, toolbarActionId); + if (objectToMove.filter(ButtonDescription.class::isInstance).isPresent()) { + ButtonDescription toolbarActionToMove = (ButtonDescription) objectToMove.get(); + if (container instanceof FormDescription) { + try { + if (container.equals(toolbarActionToMove.eContainer())) { + ((FormDescription) container).getToolbarActions().move(index, toolbarActionToMove); + } else { + ((FormDescription) container).getToolbarActions().add(index, toolbarActionToMove); + } + success = true; + } catch (IndexOutOfBoundsException exception) { + this.logger.warn(exception.getMessage(), exception); + } + } + } + } + return success; + } +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/resources/schema/formdescriptioneditor.graphqls b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/resources/schema/formdescriptioneditor.graphqls index 827ffbc982..a1b31daa46 100644 --- a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/resources/schema/formdescriptioneditor.graphqls +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/main/resources/schema/formdescriptioneditor.graphqls @@ -18,6 +18,7 @@ type FormDescriptionEditorRefreshedEventPayload { type FormDescriptionEditor implements Representation { id: ID! metadata: RepresentationMetadata! + toolbarActions: [FormDescriptionEditorToolbarAction!]! widgets: [AbstractFormDescriptionEditorWidget!]! } @@ -48,10 +49,19 @@ type FormDescriptionEditorFlexboxContainer implements AbstractFormDescriptionEdi children: [AbstractFormDescriptionEditorWidget!]! } +type FormDescriptionEditorToolbarAction implements AbstractFormDescriptionEditorWidget { + id: ID! + kind: String! + label: String! +} + extend type Mutation { addWidget(input: AddWidgetInput!): AddWidgetPayload! deleteWidget(input: DeleteWidgetInput!): DeleteWidgetPayload! moveWidget(input: MoveWidgetInput!): MoveWidgetPayload! + addToolbarAction(input: AddToolbarActionInput!): AddToolbarActionPayload! + deleteToolbarAction(input: DeleteToolbarActionInput!): DeleteToolbarActionPayload! + moveToolbarAction(input: MoveToolbarActionInput!): MoveToolbarActionPayload! } input AddWidgetInput { @@ -95,4 +105,45 @@ union MoveWidgetPayload = MoveWidgetSuccessPayload | ErrorPayload type MoveWidgetSuccessPayload { id: ID! +} + +input AddToolbarActionInput { + id: ID! + editingContextId: ID! + representationId: ID! + containerId: ID +} + +union AddToolbarActionPayload = AddToolbarActionSuccessPayload | ErrorPayload + +type AddToolbarActionSuccessPayload { + id: ID! +} + +input DeleteToolbarActionInput { + id: ID! + editingContextId: ID! + representationId: ID! + toolbarActionId: String! +} + +union DeleteToolbarActionPayload = DeleteToolbarActionSuccessPayload | ErrorPayload + +type DeleteToolbarActionSuccessPayload { + id: ID! +} + +input MoveToolbarActionInput { + id: ID! + editingContextId: ID! + representationId: ID! + containerId: ID + toolbarActionId: String! + index: Int! +} + +union MoveToolbarActionPayload = MoveToolbarActionSuccessPayload | ErrorPayload + +type MoveToolbarActionSuccessPayload { + id: ID! } \ No newline at end of file diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/FormDescriptionEditorEventProcessorTests.java b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/FormDescriptionEditorEventProcessorTests.java index f686e7450c..4d105ee2bd 100644 --- a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/FormDescriptionEditorEventProcessorTests.java +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/FormDescriptionEditorEventProcessorTests.java @@ -49,6 +49,7 @@ public class FormDescriptionEditorEventProcessorTests { .descriptionId(FORMDESCRIPTIONEDITOR_DESCRIPTION_ID) .label(String.valueOf(0)) .targetObjectId("targetObjectId") //$NON-NLS-1$ + .toolbarActions(List.of()) .widgets(List.of()) .build(); // @formatter:on diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/TestFormDescriptionEditorBuilder.java b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/TestFormDescriptionEditorBuilder.java index b30da66166..2e4ae94a39 100644 --- a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/TestFormDescriptionEditorBuilder.java +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/TestFormDescriptionEditorBuilder.java @@ -36,6 +36,7 @@ public FormDescriptionEditor getFormDescriptionEditor(String id) { .label("formDescriptionEditorLabel") //$NON-NLS-1$ .descriptionId(UUID.randomUUID().toString()) .targetObjectId("formDescriptionEditorTargetObjectId") //$NON-NLS-1$ + .toolbarActions(List.of()) .widgets(List.of()) .build(); // @formatter:on diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/AddToolbarActionEventHandlerTests.java b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/AddToolbarActionEventHandlerTests.java new file mode 100644 index 0000000000..e13cd61d76 --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/AddToolbarActionEventHandlerTests.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.collaborative.formdescriptioneditors.handlers; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Optional; +import java.util.UUID; + +import org.eclipse.sirius.components.collaborative.api.ChangeDescription; +import org.eclipse.sirius.components.collaborative.api.ChangeKind; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.FormDescriptionEditorContext; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.TestFormDescriptionEditorBuilder; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.api.IFormDescriptionEditorContext; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.dto.AddToolbarActionInput; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.dto.AddToolbarActionSuccessPayload; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.messages.ICollaborativeFormDescriptionEditorMessageService; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IObjectService; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.view.FormDescription; +import org.eclipse.sirius.components.view.ViewFactory; +import org.junit.jupiter.api.Test; + +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import reactor.core.publisher.Sinks; +import reactor.core.publisher.Sinks.Many; +import reactor.core.publisher.Sinks.One; + +/** + * Tests of the add toolbar action event handler. + * + * @author arichard + */ +public class AddToolbarActionEventHandlerTests { + @Test + public void testAddToolbarAction() { + FormDescription formDescription = ViewFactory.eINSTANCE.createFormDescription(); + var objectService = new IObjectService.NoOp() { + @Override + public Optional getObject(IEditingContext editingContext, String objectId) { + return Optional.of(formDescription); + } + }; + var handler = new AddToolbarActionEventHandler(objectService, new ICollaborativeFormDescriptionEditorMessageService.NoOp(), new SimpleMeterRegistry()); + var input = new AddToolbarActionInput(UUID.randomUUID(), "editingContextId", "representationId", "containerId"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ + + assertThat(handler.canHandle(input)).isTrue(); + + One payloadSink = Sinks.one(); + Many changeDescriptionSink = Sinks.many().unicast().onBackpressureBuffer(); + IFormDescriptionEditorContext formDescriptionEditorContext = new FormDescriptionEditorContext(new TestFormDescriptionEditorBuilder().getFormDescriptionEditor(UUID.randomUUID().toString())); + + handler.handle(payloadSink, changeDescriptionSink, new IEditingContext.NoOp(), formDescriptionEditorContext, input); + + ChangeDescription changeDescription = changeDescriptionSink.asFlux().blockFirst(); + assertThat(changeDescription.getKind()).isEqualTo(ChangeKind.SEMANTIC_CHANGE); + + IPayload payload = payloadSink.asMono().block(); + assertThat(payload).isInstanceOf(AddToolbarActionSuccessPayload.class); + assertThat(formDescription.getToolbarActions()).hasSize(1); + } +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/DeleteToolbarActionEventHandlerTests.java b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/DeleteToolbarActionEventHandlerTests.java new file mode 100644 index 0000000000..73e16e1f8a --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/DeleteToolbarActionEventHandlerTests.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.collaborative.formdescriptioneditors.handlers; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.eclipse.sirius.components.collaborative.api.ChangeDescription; +import org.eclipse.sirius.components.collaborative.api.ChangeKind; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.FormDescriptionEditorContext; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.TestFormDescriptionEditorBuilder; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.api.IFormDescriptionEditorContext; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.dto.DeleteToolbarActionInput; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.dto.DeleteToolbarActionSuccessPayload; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.messages.ICollaborativeFormDescriptionEditorMessageService; +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.core.api.IPayload; +import org.eclipse.sirius.components.formdescriptioneditors.FormDescriptionEditor; +import org.eclipse.sirius.components.view.ButtonDescription; +import org.eclipse.sirius.components.view.FormDescription; +import org.eclipse.sirius.components.view.ViewFactory; +import org.junit.jupiter.api.Test; + +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import reactor.core.publisher.Sinks; +import reactor.core.publisher.Sinks.Many; +import reactor.core.publisher.Sinks.One; + +/** + * Tests of the delete toolbarAction event handler. + * + * @author arichard + */ +public class DeleteToolbarActionEventHandlerTests { + private static final String TOOLBAR_ACTION_ID = "toolbarActionId"; //$NON-NLS-1$ + + @Test + public void testDeleteToolbarAction() { + FormDescriptionEditor formDescriptionEditor = new TestFormDescriptionEditorBuilder().getFormDescriptionEditor(UUID.randomUUID().toString()); + + FormDescription formDescription = ViewFactory.eINSTANCE.createFormDescription(); + ButtonDescription toolbarButton = ViewFactory.eINSTANCE.createButtonDescription(); + formDescription.getToolbarActions().add(toolbarButton); + var objectService = new IObjectService.NoOp() { + @Override + public Optional getObject(IEditingContext editingContext, String objectId) { + Optional result = Optional.empty(); + if (formDescriptionEditor.getDescriptionId().equals(objectId)) { + result = Optional.of(formDescription); + } else if (TOOLBAR_ACTION_ID.equals(objectId)) { + result = Optional.of(toolbarButton); + } + return result; + } + }; + AtomicBoolean toolbarActionDeleted = new AtomicBoolean(false); + IEditService.NoOp editService = new IEditService.NoOp() { + @Override + public void delete(Object object) { + if (object == toolbarButton) { + toolbarActionDeleted.set(true); + } + } + }; + var handler = new DeleteToolbarActionEventHandler(objectService, editService, new ICollaborativeFormDescriptionEditorMessageService.NoOp(), new SimpleMeterRegistry()); + var input = new DeleteToolbarActionInput(UUID.randomUUID(), "editingContextId", "representationId", TOOLBAR_ACTION_ID); //$NON-NLS-1$//$NON-NLS-2$ + + assertThat(handler.canHandle(input)).isTrue(); + + One payloadSink = Sinks.one(); + Many changeDescriptionSink = Sinks.many().unicast().onBackpressureBuffer(); + IFormDescriptionEditorContext formDescriptionEditorContext = new FormDescriptionEditorContext(formDescriptionEditor); + + handler.handle(payloadSink, changeDescriptionSink, new IEditingContext.NoOp(), formDescriptionEditorContext, input); + + ChangeDescription changeDescription = changeDescriptionSink.asFlux().blockFirst(); + assertThat(changeDescription.getKind()).isEqualTo(ChangeKind.SEMANTIC_CHANGE); + + IPayload payload = payloadSink.asMono().block(); + assertThat(payload).isInstanceOf(DeleteToolbarActionSuccessPayload.class); + assertThat(toolbarActionDeleted).isTrue(); + } +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/MoveToolbarActionEventHandlerTests.java b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/MoveToolbarActionEventHandlerTests.java new file mode 100644 index 0000000000..c4773f1cff --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/MoveToolbarActionEventHandlerTests.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.collaborative.formdescriptioneditors.handlers; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import org.eclipse.sirius.components.collaborative.api.ChangeDescription; +import org.eclipse.sirius.components.collaborative.api.ChangeKind; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.FormDescriptionEditorContext; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.TestFormDescriptionEditorBuilder; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.api.IFormDescriptionEditorContext; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.dto.MoveToolbarActionInput; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.dto.MoveToolbarActionSuccessPayload; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.messages.ICollaborativeFormDescriptionEditorMessageService; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IObjectService; +import org.eclipse.sirius.components.core.api.IObjectService.NoOp; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.formdescriptioneditors.FormDescriptionEditor; +import org.eclipse.sirius.components.view.ButtonDescription; +import org.eclipse.sirius.components.view.FormDescription; +import org.eclipse.sirius.components.view.ViewFactory; +import org.junit.jupiter.api.Test; + +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import reactor.core.publisher.Sinks; +import reactor.core.publisher.Sinks.Many; +import reactor.core.publisher.Sinks.One; + +/** + * Tests of the move toolbarAction event handler. + * + * @author arichard + */ +public class MoveToolbarActionEventHandlerTests { + @Test + public void testMoveToolbarAction() { + + FormDescriptionEditor formDescriptionEditor = new TestFormDescriptionEditorBuilder().getFormDescriptionEditor(UUID.randomUUID().toString()); + + FormDescription formDescription = ViewFactory.eINSTANCE.createFormDescription(); + ButtonDescription toolbarButton1 = ViewFactory.eINSTANCE.createButtonDescription(); + ButtonDescription toolbarButton2 = ViewFactory.eINSTANCE.createButtonDescription(); + ButtonDescription toolbarButton3 = ViewFactory.eINSTANCE.createButtonDescription(); + formDescription.getToolbarActions().add(toolbarButton1); + formDescription.getToolbarActions().add(toolbarButton2); + formDescription.getToolbarActions().add(toolbarButton3); + + var objectService = new IObjectService.NoOp() { + @Override + public Optional getObject(IEditingContext editingContext, String objectId) { + Optional result = Optional.empty(); + if (formDescriptionEditor.getDescriptionId().equals(objectId)) { + result = Optional.of(formDescription); + } else if ("button1".equals(objectId)) { //$NON-NLS-1$ + result = Optional.of(toolbarButton1); + } else if ("button2".equals(objectId)) { //$NON-NLS-1$ + result = Optional.of(toolbarButton2); + } else if ("button3".equals(objectId)) { //$NON-NLS-1$ + result = Optional.of(toolbarButton3); + } + return result; + } + }; + + this.invokMove(formDescriptionEditor, objectService, "button2", 0); //$NON-NLS-1$ + assertThat(formDescription.getToolbarActions()).isEqualTo(List.of(toolbarButton2, toolbarButton1, toolbarButton3)); + this.invokMove(formDescriptionEditor, objectService, "button1", 2); //$NON-NLS-1$ + assertThat(formDescription.getToolbarActions()).isEqualTo(List.of(toolbarButton2, toolbarButton3, toolbarButton1)); + } + + private void invokMove(FormDescriptionEditor formDescriptionEditor, NoOp objectService, String toolbarActionId, int index) { + var handler = new MoveToolbarActionEventHandler(objectService, new ICollaborativeFormDescriptionEditorMessageService.NoOp(), new SimpleMeterRegistry()); + var input = new MoveToolbarActionInput(UUID.randomUUID(), "editingContextId", formDescriptionEditor.getId(), formDescriptionEditor.getDescriptionId(), toolbarActionId, index); //$NON-NLS-1$ + + assertThat(handler.canHandle(input)).isTrue(); + + One payloadSink = Sinks.one(); + Many changeDescriptionSink = Sinks.many().unicast().onBackpressureBuffer(); + IFormDescriptionEditorContext formDescriptionEditorContext = new FormDescriptionEditorContext(new TestFormDescriptionEditorBuilder().getFormDescriptionEditor(UUID.randomUUID().toString())); + + handler.handle(payloadSink, changeDescriptionSink, new IEditingContext.NoOp(), formDescriptionEditorContext, input); + + ChangeDescription changeDescription = changeDescriptionSink.asFlux().blockFirst(); + assertThat(changeDescription.getKind()).isEqualTo(ChangeKind.SEMANTIC_CHANGE); + + IPayload payload = payloadSink.asMono().block(); + assertThat(payload).isInstanceOf(MoveToolbarActionSuccessPayload.class); + } +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/RenameFormDescriptionEditorEventHandlerTests.java b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/RenameFormDescriptionEditorEventHandlerTests.java index 7e9f02fe9d..f3efdfd8ce 100644 --- a/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/RenameFormDescriptionEditorEventHandlerTests.java +++ b/packages/formdescriptioneditors/backend/sirius-components-collaborative-formdescriptioneditors/src/test/java/org/eclipse/sirius/components/collaborative/formdescriptioneditors/handlers/RenameFormDescriptionEditorEventHandlerTests.java @@ -56,6 +56,7 @@ public void testRenameRepresentation() { .label(OLD_LABEL) .descriptionId(formDescriptionEditorDescriptionId) .targetObjectId(targetObjectId.toString()) + .toolbarActions(List.of()) .widgets(List.of()) .build(); // @formatter:on diff --git a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors-graphql/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/graphql/datafetchers/mutation/MutationAddToolbarActionDataFetcher.java b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors-graphql/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/graphql/datafetchers/mutation/MutationAddToolbarActionDataFetcher.java new file mode 100644 index 0000000000..5b273aebfb --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors-graphql/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/graphql/datafetchers/mutation/MutationAddToolbarActionDataFetcher.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.formdescriptioneditors.graphql.datafetchers.mutation; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.sirius.components.annotations.spring.graphql.MutationDataFetcher; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.dto.AddToolbarActionInput; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates; +import org.eclipse.sirius.components.graphql.api.IEditingContextDispatcher; +import org.eclipse.sirius.components.graphql.api.IExceptionWrapper; + +import graphql.schema.DataFetchingEnvironment; + +/** + * The data fetcher used to add a toolbar action from a Form Description Editor. + * + * @author arichard + */ +@MutationDataFetcher(type = "Mutation", field = "addToolbarAction") +public class MutationAddToolbarActionDataFetcher implements IDataFetcherWithFieldCoordinates> { + + private static final String INPUT_ARGUMENT = "input"; //$NON-NLS-1$ + + private final ObjectMapper objectMapper; + + private final IExceptionWrapper exceptionWrapper; + + private final IEditingContextDispatcher editingContextDispatcher; + + public MutationAddToolbarActionDataFetcher(ObjectMapper objectMapper, IExceptionWrapper exceptionWrapper, IEditingContextDispatcher editingContextDispatcher) { + this.objectMapper = Objects.requireNonNull(objectMapper); + this.exceptionWrapper = Objects.requireNonNull(exceptionWrapper); + this.editingContextDispatcher = Objects.requireNonNull(editingContextDispatcher); + } + + @Override + public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { + Object argument = environment.getArgument(INPUT_ARGUMENT); + var input = this.objectMapper.convertValue(argument, AddToolbarActionInput.class); + + return this.exceptionWrapper.wrapMono(() -> this.editingContextDispatcher.dispatchMutation(input.getEditingContextId(), input), input).toFuture(); + } +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors-graphql/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/graphql/datafetchers/mutation/MutationDeleteToolbarActionDataFetcher.java b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors-graphql/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/graphql/datafetchers/mutation/MutationDeleteToolbarActionDataFetcher.java new file mode 100644 index 0000000000..7fd6e33dc6 --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors-graphql/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/graphql/datafetchers/mutation/MutationDeleteToolbarActionDataFetcher.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.formdescriptioneditors.graphql.datafetchers.mutation; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.sirius.components.annotations.spring.graphql.MutationDataFetcher; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.dto.DeleteToolbarActionInput; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates; +import org.eclipse.sirius.components.graphql.api.IEditingContextDispatcher; +import org.eclipse.sirius.components.graphql.api.IExceptionWrapper; + +import graphql.schema.DataFetchingEnvironment; + +/** + * The data fetcher used to delete a toolbar action from a Form Description Editor. + * + * @author arichard + */ +@MutationDataFetcher(type = "Mutation", field = "deleteToolbarAction") +public class MutationDeleteToolbarActionDataFetcher implements IDataFetcherWithFieldCoordinates> { + + private static final String INPUT_ARGUMENT = "input"; //$NON-NLS-1$ + + private final ObjectMapper objectMapper; + + private final IExceptionWrapper exceptionWrapper; + + private final IEditingContextDispatcher editingContextDispatcher; + + public MutationDeleteToolbarActionDataFetcher(ObjectMapper objectMapper, IExceptionWrapper exceptionWrapper, IEditingContextDispatcher editingContextDispatcher) { + this.objectMapper = Objects.requireNonNull(objectMapper); + this.exceptionWrapper = Objects.requireNonNull(exceptionWrapper); + this.editingContextDispatcher = Objects.requireNonNull(editingContextDispatcher); + } + + @Override + public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { + Object argument = environment.getArgument(INPUT_ARGUMENT); + var input = this.objectMapper.convertValue(argument, DeleteToolbarActionInput.class); + + return this.exceptionWrapper.wrapMono(() -> this.editingContextDispatcher.dispatchMutation(input.getEditingContextId(), input), input).toFuture(); + } +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors-graphql/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/graphql/datafetchers/mutation/MutationMoveToolbarActionDataFetcher.java b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors-graphql/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/graphql/datafetchers/mutation/MutationMoveToolbarActionDataFetcher.java new file mode 100644 index 0000000000..20a9fcf2e0 --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors-graphql/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/graphql/datafetchers/mutation/MutationMoveToolbarActionDataFetcher.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.formdescriptioneditors.graphql.datafetchers.mutation; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.sirius.components.annotations.spring.graphql.MutationDataFetcher; +import org.eclipse.sirius.components.collaborative.formdescriptioneditors.dto.MoveToolbarActionInput; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates; +import org.eclipse.sirius.components.graphql.api.IEditingContextDispatcher; +import org.eclipse.sirius.components.graphql.api.IExceptionWrapper; + +import graphql.schema.DataFetchingEnvironment; + +/** + * The data fetcher used to move a toolbar action from a Form Description Editor. + * + * @author arichard + */ +@MutationDataFetcher(type = "Mutation", field = "moveToolbarAction") +public class MutationMoveToolbarActionDataFetcher implements IDataFetcherWithFieldCoordinates> { + + private static final String INPUT_ARGUMENT = "input"; //$NON-NLS-1$ + + private final ObjectMapper objectMapper; + + private final IExceptionWrapper exceptionWrapper; + + private final IEditingContextDispatcher editingContextDispatcher; + + public MutationMoveToolbarActionDataFetcher(ObjectMapper objectMapper, IExceptionWrapper exceptionWrapper, IEditingContextDispatcher editingContextDispatcher) { + this.objectMapper = Objects.requireNonNull(objectMapper); + this.exceptionWrapper = Objects.requireNonNull(exceptionWrapper); + this.editingContextDispatcher = Objects.requireNonNull(editingContextDispatcher); + } + + @Override + public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { + Object argument = environment.getArgument(INPUT_ARGUMENT); + var input = this.objectMapper.convertValue(argument, MoveToolbarActionInput.class); + + return this.exceptionWrapper.wrapMono(() -> this.editingContextDispatcher.dispatchMutation(input.getEditingContextId(), input), input).toFuture(); + } +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/FormDescriptionEditor.java b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/FormDescriptionEditor.java index d24c3bfa57..4cffa7dc2f 100644 --- a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/FormDescriptionEditor.java +++ b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/FormDescriptionEditor.java @@ -42,6 +42,8 @@ public final class FormDescriptionEditor implements IRepresentation, ISemanticRe private String descriptionId; + private List toolbarActions; + private List widgets; private FormDescriptionEditor() { @@ -73,6 +75,10 @@ public String getDescriptionId() { return this.descriptionId; } + public List getToolbarActions() { + return this.toolbarActions; + } + public List getWidgets() { return this.widgets; } @@ -108,6 +114,8 @@ public static final class Builder { private String descriptionId; + private List toolbarActions; + private List widgets; private Builder(String id) { @@ -119,6 +127,7 @@ public Builder(FormDescriptionEditor formDescriptionEditor) { this.label = formDescriptionEditor.label; this.targetObjectId = formDescriptionEditor.targetObjectId; this.descriptionId = formDescriptionEditor.descriptionId; + this.toolbarActions = formDescriptionEditor.toolbarActions; this.widgets = formDescriptionEditor.widgets; } @@ -137,6 +146,11 @@ public Builder descriptionId(String descriptionId) { return this; } + public Builder toolbarActions(List toolbarActions) { + this.toolbarActions = Objects.requireNonNull(toolbarActions); + return this; + } + public Builder widgets(List widgets) { this.widgets = Objects.requireNonNull(widgets); return this; @@ -149,6 +163,7 @@ public FormDescriptionEditor build() { formDescriptionEditor.label = Objects.requireNonNull(this.label); formDescriptionEditor.targetObjectId = Objects.requireNonNull(this.targetObjectId); formDescriptionEditor.descriptionId = Objects.requireNonNull(this.descriptionId); + formDescriptionEditor.toolbarActions = Objects.requireNonNull(this.toolbarActions); formDescriptionEditor.widgets = Objects.requireNonNull(this.widgets); return formDescriptionEditor; } diff --git a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/FormDescriptionEditorToolbarAction.java b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/FormDescriptionEditorToolbarAction.java new file mode 100644 index 0000000000..ccea98afc5 --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/FormDescriptionEditorToolbarAction.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.formdescriptioneditors; + +import java.text.MessageFormat; +import java.util.Objects; + +import org.eclipse.sirius.components.annotations.Immutable; + +/** + * Any widget contained in the form description editor toolbar action. + * + * @author arichard + */ +@Immutable +public final class FormDescriptionEditorToolbarAction extends AbstractFormDescriptionEditorWidget { + + private FormDescriptionEditorToolbarAction() { + // Prevent instantiation + } + + public static Builder newFormDescriptionEditorToolbarAction(String id) { + return new Builder(id); + } + + @Override + public String toString() { + String pattern = "{0} '{'id: {1}, kind: {2}, label: {3}'}'"; //$NON-NLS-1$ + return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.id, this.kind, this.label); + } + + /** + * The builder used to create the form description editor toolbar action. + * + * @author arichard + */ + @SuppressWarnings("checkstyle:HiddenField") + public static final class Builder { + private String id; + + private String kind; + + private String label; + + private Builder(String id) { + this.id = Objects.requireNonNull(id); + } + + public Builder kind(String kind) { + this.kind = Objects.requireNonNull(kind); + return this; + } + + public Builder label(String label) { + this.label = Objects.requireNonNull(label); + return this; + } + + public FormDescriptionEditorToolbarAction build() { + FormDescriptionEditorToolbarAction formDescriptionEditorWidget = new FormDescriptionEditorToolbarAction(); + formDescriptionEditorWidget.id = Objects.requireNonNull(this.id); + formDescriptionEditorWidget.kind = Objects.requireNonNull(this.kind); + formDescriptionEditorWidget.label = Objects.requireNonNull(this.label); + return formDescriptionEditorWidget; + } + } +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/components/FormDescriptionEditorComponent.java b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/components/FormDescriptionEditorComponent.java index 83c44567c0..c7a1ac19a3 100644 --- a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/components/FormDescriptionEditorComponent.java +++ b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/components/FormDescriptionEditorComponent.java @@ -21,6 +21,7 @@ import org.eclipse.sirius.components.formdescriptioneditors.description.AbstractFormDescriptionEditorWidgetDescription; import org.eclipse.sirius.components.formdescriptioneditors.description.FormDescriptionEditorDescription; import org.eclipse.sirius.components.formdescriptioneditors.description.FormDescriptionEditorFlexboxContainerDescription; +import org.eclipse.sirius.components.formdescriptioneditors.description.FormDescriptionEditorToolbarActionDescription; import org.eclipse.sirius.components.formdescriptioneditors.description.FormDescriptionEditorWidgetDescription; import org.eclipse.sirius.components.formdescriptioneditors.elements.FormDescriptionEditorElementProps; import org.eclipse.sirius.components.representations.Element; @@ -62,6 +63,25 @@ public Element render() { List childrenWidgets = new ArrayList<>(); + formDescription.getToolbarActions().forEach(toolbarActionDescription -> { + VariableManager childVariableManager = variableManager.createChild(); + childVariableManager.put(VariableManager.SELF, toolbarActionDescription); + String toolbarActionId = targetObjectIdProvider.apply(childVariableManager); + String toolbarActionKind = this.getKind(toolbarActionDescription); + String toolbarActionLabel = toolbarActionDescription.getName(); + if (toolbarActionLabel == null) { + toolbarActionLabel = toolbarActionKind; + } + // @formatter:off + FormDescriptionEditorToolbarActionDescription fdeToolbarActionDescription = FormDescriptionEditorToolbarActionDescription.newFormDescriptionEditorToolbarActionDescription(toolbarActionId) + .label(toolbarActionLabel) + .kind(toolbarActionKind) + .build(); + // @formatter:on + FormDescriptionEditorToolbarActionComponentProps fdeToolbarActionComponentProps = new FormDescriptionEditorToolbarActionComponentProps(fdeToolbarActionDescription); + childrenWidgets.add(new Element(FormDescriptionEditorToolbarActionComponent.class, fdeToolbarActionComponentProps)); + }); + formDescription.getWidgets().forEach(widgetDescription -> { VariableManager childVariableManager = variableManager.createChild(); diff --git a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/components/FormDescriptionEditorToolbarActionComponent.java b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/components/FormDescriptionEditorToolbarActionComponent.java new file mode 100644 index 0000000000..6c10e9a26a --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/components/FormDescriptionEditorToolbarActionComponent.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.formdescriptioneditors.components; + +import java.util.Objects; + +import org.eclipse.sirius.components.formdescriptioneditors.description.FormDescriptionEditorToolbarActionDescription; +import org.eclipse.sirius.components.formdescriptioneditors.elements.FormDescriptionEditorToolbarActionElementProps; +import org.eclipse.sirius.components.representations.Element; +import org.eclipse.sirius.components.representations.IComponent; + +/** + * The component used to render the form description editor toolbar action. + * + * @author arichard + */ +public class FormDescriptionEditorToolbarActionComponent implements IComponent { + + private final FormDescriptionEditorToolbarActionComponentProps props; + + public FormDescriptionEditorToolbarActionComponent(FormDescriptionEditorToolbarActionComponentProps props) { + this.props = Objects.requireNonNull(props); + } + + @Override + public Element render() { + FormDescriptionEditorToolbarActionDescription formDescriptionEditorToolbarActionDescription = this.props.getFormDescriptionEditorToolbarActionDescription(); + + String id = formDescriptionEditorToolbarActionDescription.getId(); + String label = formDescriptionEditorToolbarActionDescription.getLabel(); + String kind = formDescriptionEditorToolbarActionDescription.getKind(); + + // @formatter:off + FormDescriptionEditorToolbarActionElementProps toolbarActionPropsBuilder = FormDescriptionEditorToolbarActionElementProps.newFormDescriptionEditorToolbarActionElementProps(id) + .label(label) + .kind(kind) + .build(); + // @formatter:on + + return new Element(FormDescriptionEditorToolbarActionElementProps.TYPE, toolbarActionPropsBuilder); + } +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/components/FormDescriptionEditorToolbarActionComponentProps.java b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/components/FormDescriptionEditorToolbarActionComponentProps.java new file mode 100644 index 0000000000..d4f2abc1e9 --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/components/FormDescriptionEditorToolbarActionComponentProps.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.formdescriptioneditors.components; + +import java.util.Objects; + +import org.eclipse.sirius.components.formdescriptioneditors.description.FormDescriptionEditorToolbarActionDescription; +import org.eclipse.sirius.components.representations.IProps; + +/** + * * The properties of the form description editor toolbar action component. + * + * @author arichard + */ +public class FormDescriptionEditorToolbarActionComponentProps implements IProps { + + private final FormDescriptionEditorToolbarActionDescription formDescriptionEditorToolbarActionDescription; + + public FormDescriptionEditorToolbarActionComponentProps(FormDescriptionEditorToolbarActionDescription formDescriptionEditorToolbarActionDescription) { + this.formDescriptionEditorToolbarActionDescription = Objects.requireNonNull(formDescriptionEditorToolbarActionDescription); + } + + public FormDescriptionEditorToolbarActionDescription getFormDescriptionEditorToolbarActionDescription() { + return this.formDescriptionEditorToolbarActionDescription; + } +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/description/FormDescriptionEditorToolbarActionDescription.java b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/description/FormDescriptionEditorToolbarActionDescription.java new file mode 100644 index 0000000000..0d17afc7e1 --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/description/FormDescriptionEditorToolbarActionDescription.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.formdescriptioneditors.description; + +import java.text.MessageFormat; +import java.util.Objects; + +import org.eclipse.sirius.components.annotations.Immutable; + +/** + * The root concept of the description of a form description editor widget. + * + * @author arichard + */ +@Immutable +public final class FormDescriptionEditorToolbarActionDescription extends AbstractFormDescriptionEditorWidgetDescription { + + private FormDescriptionEditorToolbarActionDescription() { + // Prevent instantiation + } + + @Override + public String getId() { + return this.id; + } + + @Override + public String getLabel() { + return this.label; + } + + @Override + public String getKind() { + return this.kind; + } + + public static Builder newFormDescriptionEditorToolbarActionDescription(String id) { + return new Builder(id); + } + + @Override + public String toString() { + String pattern = "{0} '{'id: {1}, label: {2}, kind: {3}'}'"; //$NON-NLS-1$ + return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.id, this.label, this.kind); + } + + /** + * Builder used to create the form description editor toolbar action description. + * + * @author arichard + */ + @SuppressWarnings("checkstyle:HiddenField") + public static final class Builder { + private String id; + + private String label; + + private String kind; + + private Builder(String id) { + this.id = Objects.requireNonNull(id); + } + + public Builder label(String label) { + this.label = Objects.requireNonNull(label); + return this; + } + + public Builder kind(String kind) { + this.kind = Objects.requireNonNull(kind); + return this; + } + + public FormDescriptionEditorToolbarActionDescription build() { + FormDescriptionEditorToolbarActionDescription formDescriptionEditorToolbarActionDescription = new FormDescriptionEditorToolbarActionDescription(); + formDescriptionEditorToolbarActionDescription.id = Objects.requireNonNull(this.id); + formDescriptionEditorToolbarActionDescription.label = Objects.requireNonNull(this.label); + formDescriptionEditorToolbarActionDescription.kind = Objects.requireNonNull(this.kind); + return formDescriptionEditorToolbarActionDescription; + } + } +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/elements/FormDescriptionEditorToolbarActionElementProps.java b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/elements/FormDescriptionEditorToolbarActionElementProps.java new file mode 100644 index 0000000000..6109244149 --- /dev/null +++ b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/elements/FormDescriptionEditorToolbarActionElementProps.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2022 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.components.formdescriptioneditors.elements; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import org.eclipse.sirius.components.annotations.Immutable; +import org.eclipse.sirius.components.representations.Element; +import org.eclipse.sirius.components.representations.IProps; + +/** + * The properties of the form description editor toolbar action element. + * + * @author arichard + */ +@Immutable +public final class FormDescriptionEditorToolbarActionElementProps implements IProps { + public static final String TYPE = "FormDescriptionEditorToolbarAction"; //$NON-NLS-1$ + + private String id; + + private String label; + + private String kind; + + private FormDescriptionEditorToolbarActionElementProps() { + // Prevent instantiation + } + + public String getId() { + return this.id; + } + + public String getLabel() { + return this.label; + } + + public String getKind() { + return this.kind; + } + + @Override + public List getChildren() { + return new ArrayList<>(); + } + + public static Builder newFormDescriptionEditorToolbarActionElementProps(String id) { + return new Builder(id); + } + + @Override + public String toString() { + String pattern = "{0} '{'id: {1}, label: {2}'}'"; //$NON-NLS-1$ + return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.id, this.label); + } + + /** + * The builder of the form description editor toolbar action element props. + * + * @author arichard + */ + @SuppressWarnings("checkstyle:HiddenField") + public static final class Builder { + private String id; + + private String label; + + private String kind; + + private Builder(String id) { + this.id = Objects.requireNonNull(id); + } + + public Builder label(String label) { + this.label = Objects.requireNonNull(label); + return this; + } + + public Builder kind(String kind) { + this.kind = Objects.requireNonNull(kind); + return this; + } + + public FormDescriptionEditorToolbarActionElementProps build() { + FormDescriptionEditorToolbarActionElementProps toolbarActionElementProps = new FormDescriptionEditorToolbarActionElementProps(); + toolbarActionElementProps.id = Objects.requireNonNull(this.id); + toolbarActionElementProps.label = Objects.requireNonNull(this.label); + toolbarActionElementProps.kind = Objects.requireNonNull(this.kind); + return toolbarActionElementProps; + } + } +} diff --git a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/renderer/FormDescriptionEditorComponentPropsValidator.java b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/renderer/FormDescriptionEditorComponentPropsValidator.java index f0d2c5ffed..abbab53630 100644 --- a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/renderer/FormDescriptionEditorComponentPropsValidator.java +++ b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/renderer/FormDescriptionEditorComponentPropsValidator.java @@ -14,10 +14,12 @@ import org.eclipse.sirius.components.formdescriptioneditors.components.FormDescriptionEditorComponent; import org.eclipse.sirius.components.formdescriptioneditors.components.FormDescriptionEditorComponentProps; -import org.eclipse.sirius.components.formdescriptioneditors.components.FormDescriptionEditorWidgetComponent; -import org.eclipse.sirius.components.formdescriptioneditors.components.FormDescriptionEditorWidgetComponentProps; import org.eclipse.sirius.components.formdescriptioneditors.components.FormDescriptionEditorFlexboxContainerComponent; import org.eclipse.sirius.components.formdescriptioneditors.components.FormDescriptionEditorFlexboxContainerComponentProps; +import org.eclipse.sirius.components.formdescriptioneditors.components.FormDescriptionEditorToolbarActionComponent; +import org.eclipse.sirius.components.formdescriptioneditors.components.FormDescriptionEditorToolbarActionComponentProps; +import org.eclipse.sirius.components.formdescriptioneditors.components.FormDescriptionEditorWidgetComponent; +import org.eclipse.sirius.components.formdescriptioneditors.components.FormDescriptionEditorWidgetComponentProps; import org.eclipse.sirius.components.representations.IComponentPropsValidator; import org.eclipse.sirius.components.representations.IProps; @@ -38,6 +40,8 @@ public boolean validateComponentProps(Class componentType, IProps props) { checkValidProps = props instanceof FormDescriptionEditorWidgetComponentProps; } else if (FormDescriptionEditorFlexboxContainerComponent.class.equals(componentType)) { checkValidProps = props instanceof FormDescriptionEditorFlexboxContainerComponentProps; + } else if (FormDescriptionEditorToolbarActionComponent.class.equals(componentType)) { + checkValidProps = props instanceof FormDescriptionEditorToolbarActionComponentProps; } return checkValidProps; } diff --git a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/renderer/FormDescriptionEditorElementFactory.java b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/renderer/FormDescriptionEditorElementFactory.java index b51f1cc7bb..9e068c1623 100644 --- a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/renderer/FormDescriptionEditorElementFactory.java +++ b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/renderer/FormDescriptionEditorElementFactory.java @@ -18,9 +18,11 @@ import org.eclipse.sirius.components.formdescriptioneditors.AbstractFormDescriptionEditorWidget; import org.eclipse.sirius.components.formdescriptioneditors.FormDescriptionEditor; import org.eclipse.sirius.components.formdescriptioneditors.FormDescriptionEditorFlexboxContainer; +import org.eclipse.sirius.components.formdescriptioneditors.FormDescriptionEditorToolbarAction; import org.eclipse.sirius.components.formdescriptioneditors.FormDescriptionEditorWidget; import org.eclipse.sirius.components.formdescriptioneditors.elements.FormDescriptionEditorElementProps; import org.eclipse.sirius.components.formdescriptioneditors.elements.FormDescriptionEditorFlexboxContainerElementProps; +import org.eclipse.sirius.components.formdescriptioneditors.elements.FormDescriptionEditorToolbarActionElementProps; import org.eclipse.sirius.components.formdescriptioneditors.elements.FormDescriptionEditorWidgetElementProps; import org.eclipse.sirius.components.representations.IElementFactory; import org.eclipse.sirius.components.representations.IProps; @@ -41,14 +43,22 @@ public Object instantiateElement(String type, IProps props, List childre object = this.instantiateWidget((FormDescriptionEditorWidgetElementProps) props, children); } else if (FormDescriptionEditorFlexboxContainerElementProps.TYPE.equals(type) && props instanceof FormDescriptionEditorFlexboxContainerElementProps) { object = this.instantiateFlexboxContainer((FormDescriptionEditorFlexboxContainerElementProps) props, children); + } else if (FormDescriptionEditorToolbarActionElementProps.TYPE.equals(type) && props instanceof FormDescriptionEditorToolbarActionElementProps) { + object = this.instantiateToolbarAction((FormDescriptionEditorToolbarActionElementProps) props, children); } return object; } private FormDescriptionEditor instantiateForm(FormDescriptionEditorElementProps props, List children) { // @formatter:off + List toolbarActions = children.stream() + .filter(FormDescriptionEditorToolbarAction.class::isInstance) + .map(FormDescriptionEditorToolbarAction.class::cast) + .collect(Collectors.toList()); + List widgets = children.stream() .filter(AbstractFormDescriptionEditorWidget.class::isInstance) + .filter(c -> !(c instanceof FormDescriptionEditorToolbarAction)) .map(AbstractFormDescriptionEditorWidget.class::cast) .collect(Collectors.toList()); @@ -56,6 +66,7 @@ private FormDescriptionEditor instantiateForm(FormDescriptionEditorElementProps .label(props.getLabel()) .targetObjectId(props.getTargetObjectId()) .descriptionId(props.getDescriptionId()) + .toolbarActions(toolbarActions) .widgets(widgets) .build(); // @formatter:on @@ -87,4 +98,13 @@ private FormDescriptionEditorFlexboxContainer instantiateFlexboxContainer(FormDe .build(); // @formatter:on } + + private FormDescriptionEditorToolbarAction instantiateToolbarAction(FormDescriptionEditorToolbarActionElementProps props, List children) { + // @formatter:off + return FormDescriptionEditorToolbarAction.newFormDescriptionEditorToolbarAction(props.getId()) + .label(props.getLabel()) + .kind(props.getKind()) + .build(); + // @formatter:on + } } diff --git a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/renderer/FormDescriptionEditorInstancePropsValidator.java b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/renderer/FormDescriptionEditorInstancePropsValidator.java index a355b91da2..cfecce0ce5 100644 --- a/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/renderer/FormDescriptionEditorInstancePropsValidator.java +++ b/packages/formdescriptioneditors/backend/sirius-components-formdescriptioneditors/src/main/java/org/eclipse/sirius/components/formdescriptioneditors/renderer/FormDescriptionEditorInstancePropsValidator.java @@ -14,6 +14,7 @@ import org.eclipse.sirius.components.formdescriptioneditors.elements.FormDescriptionEditorElementProps; import org.eclipse.sirius.components.formdescriptioneditors.elements.FormDescriptionEditorFlexboxContainerElementProps; +import org.eclipse.sirius.components.formdescriptioneditors.elements.FormDescriptionEditorToolbarActionElementProps; import org.eclipse.sirius.components.formdescriptioneditors.elements.FormDescriptionEditorWidgetElementProps; import org.eclipse.sirius.components.representations.IInstancePropsValidator; import org.eclipse.sirius.components.representations.IProps; @@ -35,6 +36,8 @@ public boolean validateInstanceProps(String type, IProps props) { checkValidProps = props instanceof FormDescriptionEditorWidgetElementProps; } else if (FormDescriptionEditorFlexboxContainerElementProps.TYPE.equals(type)) { checkValidProps = props instanceof FormDescriptionEditorFlexboxContainerElementProps; + } else if (FormDescriptionEditorToolbarActionElementProps.TYPE.equals(type)) { + checkValidProps = props instanceof FormDescriptionEditorToolbarActionElementProps; } return checkValidProps; } diff --git a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ButtonWidget.tsx b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ButtonWidget.tsx index c2576fa0ff..016b9d2c1b 100644 --- a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ButtonWidget.tsx +++ b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ButtonWidget.tsx @@ -13,8 +13,8 @@ import Button from '@material-ui/core/Button'; import { makeStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; -import { WidgetProps } from './WidgetEntry.types'; import { useEffect, useRef, useState } from 'react'; +import { WidgetProps } from './WidgetEntry.types'; const useStyles = makeStyles((theme) => ({ selected: { diff --git a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FlexboxContainerWidget.tsx b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FlexboxContainerWidget.tsx index a34ff3b5b4..48f4a24f1e 100644 --- a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FlexboxContainerWidget.tsx +++ b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FlexboxContainerWidget.tsx @@ -67,6 +67,7 @@ const useStyles = makeStyles((theme) => export const FlexboxContainerWidget = ({ editingContextId, representationId, + toolbarActions, widget, selection, setSelection, @@ -195,6 +196,7 @@ export const FlexboxContainerWidget = ({ editingContextId={editingContextId} representationId={representationId} containerId={widget.id} + toolbarActions={toolbarActions} siblings={widget.children} widget={childWidget} selection={selection} diff --git a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FormDescriptionEditorEventFragment.ts b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FormDescriptionEditorEventFragment.ts index 077d685d2e..2da52baeac 100644 --- a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FormDescriptionEditorEventFragment.ts +++ b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FormDescriptionEditorEventFragment.ts @@ -37,6 +37,11 @@ export const formDescriptionEditorEventSubscription = gql` id } } + toolbarActions { + id + label + kind + } widgets { id label @@ -119,3 +124,45 @@ export const moveWidgetMutation = gql` } } `; + +export const addToolbarActionMutation = gql` + mutation addToolbarAction($input: AddToolbarActionInput!) { + addToolbarAction(input: $input) { + __typename + ... on AddToolbarActionSuccessPayload { + id + } + ... on ErrorPayload { + message + } + } + } +`; + +export const deleteToolbarActionMutation = gql` + mutation deleteToolbarAction($input: DeleteToolbarActionInput!) { + deleteToolbarAction(input: $input) { + __typename + ... on DeleteToolbarActionSuccessPayload { + id + } + ... on ErrorPayload { + message + } + } + } +`; + +export const moveToolbarActionMutation = gql` + mutation moveToolbarAction($input: MoveToolbarActionInput!) { + moveToolbarAction(input: $input) { + __typename + ... on MoveToolbarActionSuccessPayload { + id + } + ... on ErrorPayload { + message + } + } + } +`; diff --git a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FormDescriptionEditorEventFragment.types.ts b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FormDescriptionEditorEventFragment.types.ts index 2a865776f8..2f633b52d9 100644 --- a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FormDescriptionEditorEventFragment.types.ts +++ b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FormDescriptionEditorEventFragment.types.ts @@ -71,6 +71,7 @@ export interface GQLRepresentationDescription { export interface GQLFormDescriptionEditor extends GQLRepresentation { id: string; metadata: GQLRepresentationMetadata; + toolbarActions: GQLFormDescriptionEditorToolbarAction[]; widgets: GQLAbstractFormDescriptionEditorWidget[]; } @@ -89,6 +90,8 @@ export interface GQLFormDescriptionEditorFlexboxContainer extends GQLAbstractFor children: GQLAbstractFormDescriptionEditorWidget[]; } +export interface GQLFormDescriptionEditorToolbarAction extends GQLAbstractFormDescriptionEditorWidget {} + export interface GQLAddWidgetInput { id: string; editingContextId: string; @@ -162,6 +165,83 @@ export interface GQLMoveWidgetSuccessPayload extends GQLMoveWidgetPayload { id: string; } -export interface GQLErrorPayload extends GQLAddWidgetPayload, GQLDeleteWidgetPayload, GQLMoveWidgetPayload { +export interface GQLAddToolbarActionInput { + id: string; + editingContextId: string; + representationId: string; + containerId: string | null; +} + +export interface GQLAddToolbarActionMutationVariables { + input: GQLAddToolbarActionInput; +} + +export interface GQLAddToolbarActionMutationData { + addToolbarAction: GQLAddToolbarActionPayload; +} + +export interface GQLAddToolbarActionPayload { + __typename: string; +} + +export interface GQLAddToolbarActionSuccessPayload extends GQLAddToolbarActionPayload { + id: string; +} + +export interface GQLDeleteToolbarActionInput { + id: string; + editingContextId: string; + representationId: string; + toolbarActionId: string; +} + +export interface GQLDeleteToolbarActionMutationVariables { + input: GQLDeleteToolbarActionInput; +} + +export interface GQLDeleteToolbarActionMutationData { + deleteToolbarAction: GQLDeleteToolbarActionPayload; +} + +export interface GQLDeleteToolbarActionPayload { + __typename: string; +} + +export interface GQLDeleteToolbarActionSuccessPayload extends GQLDeleteToolbarActionPayload { + id: string; +} + +export interface GQLMoveToolbarActionInput { + id: string; + editingContextId: string; + representationId: string; + containerId: string | null; + toolbarActionId: string; + index: number; +} + +export interface GQLMoveToolbarActionMutationVariables { + input: GQLMoveToolbarActionInput; +} + +export interface GQLMoveToolbarActionMutationData { + moveToolbarAction: GQLMoveToolbarActionPayload; +} + +export interface GQLMoveToolbarActionPayload { + __typename: string; +} + +export interface GQLMoveToolbarActionSuccessPayload extends GQLMoveToolbarActionPayload { + id: string; +} + +export interface GQLErrorPayload + extends GQLAddWidgetPayload, + GQLDeleteWidgetPayload, + GQLMoveWidgetPayload, + GQLAddToolbarActionPayload, + GQLDeleteToolbarActionPayload, + GQLMoveToolbarActionPayload { message: string; } diff --git a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FormDescriptionEditorRepresentation.tsx b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FormDescriptionEditorRepresentation.tsx index 7c4fbf6f51..4c3b6d7d23 100644 --- a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FormDescriptionEditorRepresentation.tsx +++ b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/FormDescriptionEditorRepresentation.tsx @@ -63,6 +63,7 @@ import { ShowToastEvent, } from './FormDescriptionEditorRepresentationMachine'; import { Button } from './icons/Button'; +import { ToolbarActions } from './ToolbarActions'; import { WidgetEntry } from './WidgetEntry'; import { isKind } from './WidgetOperations'; const isErrorPayload = (payload: GQLAddWidgetPayload | GQLMoveWidgetPayload): payload is GQLErrorPayload => @@ -73,6 +74,7 @@ const useFormDescriptionEditorStyles = makeStyles((theme) => ({ display: 'flex', flexDirection: 'column', width: '100%', + overflowX: 'auto', }, header: { padding: '4px 8px 4px 8px', @@ -90,6 +92,7 @@ const useFormDescriptionEditorStyles = makeStyles((theme) => ({ flexDirection: 'column', borderRight: '1px solid grey', padding: '4px 8px 4px 8px', + overflowY: 'auto', }, widgetKind: { display: 'flex', @@ -102,13 +105,19 @@ const useFormDescriptionEditorStyles = makeStyles((theme) => ({ preview: { width: '100%', padding: '4px 8px 4px 8px', + overflowY: 'auto', + }, + labelAndToolbar: { + display: 'flex', + flexDirection: 'row', + justifyContent: 'space-between', overflowX: 'auto', - overflowY: 'scroll', }, body: { display: 'flex', flexDirection: 'column', alignItems: 'stretch', + overflowX: 'auto', }, bottomDropArea: { height: '100px', @@ -278,7 +287,10 @@ export const FormDescriptionEditorRepresentation = ({ const addWidgetVariables: GQLAddWidgetMutationVariables = { input: addWidgetInput }; addWidget({ variables: addWidgetVariables }); } else { - if (formDescriptionEditor.widgets.find((w) => w.id === id)) { + if (formDescriptionEditor.toolbarActions.find((w) => w.id === id)) { + // forbid to drag and drop toolbarAction into widgets area + return; + } else if (formDescriptionEditor.widgets.find((w) => w.id === id)) { index--; } const moveWidgetInput: GQLMoveWidgetInput = { @@ -457,7 +469,17 @@ export const FormDescriptionEditorRepresentation = ({
- Preview +
+ Preview + +
{formDescriptionEditor.widgets.map((widget) => ( (() => ({ + style: { + minWidth: '32px', + lineHeight: 1.25, + }, + toolbarAction: { + display: 'flex', + flexDirection: 'row', + flexGrow: 1, + }, + placeholder: { + height: 'inherit', + width: '20px', + }, + dragOver: { + border: 'dashed 1px red', + }, +})); + +const isErrorPayload = (payload: GQLDeleteToolbarActionPayload): payload is GQLErrorPayload => + payload.__typename === 'ErrorPayload'; + +export const ToolbarActionWidget = ({ + editingContextId, + representationId, + siblings, + toolbarAction, + selection, + setSelection, +}: ToolbarActionProps) => { + const classes = useStyle(); + + const initialState: ToolbarActionState = { message: null, selected: false }; + const [state, setState] = useState(initialState); + + const ref = useRef(null); + + useEffect(() => { + if (ref.current && selection.entries.find((entry) => entry.id === toolbarAction.id)) { + ref.current.focus(); + setState({ message: state.message, selected: true }); + } else { + setState({ message: state.message, selected: false }); + } + }, [selection, toolbarAction]); + + const [ + deleteToolbarAction, + { loading: deleteToolbarActionLoading, data: deleteToolbarActionData, error: deleteToolbarActionError }, + ] = useMutation( + deleteToolbarActionMutation + ); + + useEffect(() => { + if (!deleteToolbarActionLoading) { + if (deleteToolbarActionError) { + setState({ message: deleteToolbarActionError.message, selected: state.selected }); + } + if (deleteToolbarActionData) { + const { deleteToolbarAction } = deleteToolbarActionData; + if (isErrorPayload(deleteToolbarAction)) { + setState({ message: deleteToolbarAction.message, selected: state.selected }); + } + } + } + }, [deleteToolbarActionLoading, deleteToolbarActionData, deleteToolbarActionError]); + + const [ + moveToolbarAction, + { loading: moveToolbarActionLoading, data: moveToolbarActionData, error: moveToolbarActionError }, + ] = useMutation(moveToolbarActionMutation); + + useEffect(() => { + if (!moveToolbarActionLoading) { + if (moveToolbarActionError) { + setState({ message: moveToolbarActionError.message, selected: state.selected }); + } + if (moveToolbarActionData) { + const { moveToolbarAction } = moveToolbarActionData; + if (isErrorPayload(moveToolbarAction)) { + setState({ message: moveToolbarAction.message, selected: state.selected }); + } + } + } + }, [moveToolbarActionLoading, moveToolbarActionData, moveToolbarActionError]); + + const handleDragStart: React.DragEventHandler = (event: React.DragEvent) => { + event.dataTransfer.setData('text/plain', toolbarAction.id); + event.stopPropagation(); + }; + const handleDragEnter: React.DragEventHandler = (event: React.DragEvent) => { + event.preventDefault(); + event.currentTarget.classList.add(classes.dragOver); + }; + const handleDragOver: React.DragEventHandler = (event: React.DragEvent) => { + event.preventDefault(); + event.currentTarget.classList.add(classes.dragOver); + }; + const handleDragLeave: React.DragEventHandler = (event: React.DragEvent) => { + event.preventDefault(); + event.currentTarget.classList.remove(classes.dragOver); + }; + const handleDrop: React.DragEventHandler = (event: React.DragEvent) => { + event.preventDefault(); + event.currentTarget.classList.remove(classes.dragOver); + onDropBefore(event, toolbarAction); + }; + + const onDropBefore = ( + event: React.DragEvent, + toolbarAction: GQLFormDescriptionEditorToolbarAction + ) => { + const id: string = event.dataTransfer.getData('text/plain'); + + let index: number = siblings.indexOf(toolbarAction); + if (index <= 0) { + index = 0; + } + + const movedToolbarActionIndex = siblings.findIndex((tba) => tba.id === id); + if (movedToolbarActionIndex > -1 && movedToolbarActionIndex < index) { + index--; + } + const moveToolbarActionInput: GQLMoveToolbarActionInput = { + id: uuid(), + editingContextId, + representationId, + containerId: null, + toolbarActionId: id, + index, + }; + const moveToolbarActionVariables: GQLMoveToolbarActionMutationVariables = { input: moveToolbarActionInput }; + moveToolbarAction({ variables: moveToolbarActionVariables }); + }; + + const handleClick: React.MouseEventHandler = ( + event: React.MouseEvent + ) => { + const newSelection: Selection = { + entries: [ + { + id: toolbarAction.id, + label: toolbarAction.label, + kind: `siriusComponents://semantic?domain=view&entity=${toolbarAction.kind}Description`, + }, + ], + }; + setSelection(newSelection); + event.stopPropagation(); + }; + + const handleDelete: React.KeyboardEventHandler = (event: React.KeyboardEvent) => { + event.preventDefault(); + if (event.key === 'Delete') { + const deleteToolbarActionInput: GQLDeleteToolbarActionInput = { + id: uuid(), + editingContextId, + representationId, + toolbarActionId: toolbarAction.id, + }; + const deleteToolbarActionVariables: GQLDeleteToolbarActionMutationVariables = { input: deleteToolbarActionInput }; + deleteToolbarAction({ variables: deleteToolbarActionVariables }); + event.stopPropagation(); + } + }; + + return ( +
+
+ +
+ ); +}; diff --git a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ToolbarActionWidget.types.ts b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ToolbarActionWidget.types.ts new file mode 100644 index 0000000000..b87045ffa8 --- /dev/null +++ b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ToolbarActionWidget.types.ts @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2022 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 { Selection } from '@eclipse-sirius/sirius-components-core'; +import { GQLFormDescriptionEditorToolbarAction } from './FormDescriptionEditorEventFragment.types'; + +export interface ToolbarActionProps { + editingContextId: string; + representationId: string; + siblings: GQLFormDescriptionEditorToolbarAction[]; + toolbarAction: GQLFormDescriptionEditorToolbarAction; + selection: Selection; + setSelection: (newSelection: Selection) => void; +} + +export interface ToolbarActionState { + message: string | null; + selected: boolean; +} diff --git a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ToolbarActions.tsx b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ToolbarActions.tsx new file mode 100644 index 0000000000..d54f0fb562 --- /dev/null +++ b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ToolbarActions.tsx @@ -0,0 +1,205 @@ +/******************************************************************************* + * Copyright (c) 2022 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 { useMutation } from '@apollo/client'; +import IconButton from '@material-ui/core/IconButton'; +import Snackbar from '@material-ui/core/Snackbar'; +import { makeStyles, Theme } from '@material-ui/core/styles'; +import Tooltip from '@material-ui/core/Tooltip'; +import AddIcon from '@material-ui/icons/Add'; +import CloseIcon from '@material-ui/icons/Close'; +import { useEffect, useState } from 'react'; +import { v4 as uuid } from 'uuid'; +import { addToolbarActionMutation, moveToolbarActionMutation } from './FormDescriptionEditorEventFragment'; +import { + GQLAddToolbarActionInput, + GQLAddToolbarActionMutationData, + GQLAddToolbarActionMutationVariables, + GQLAddToolbarActionPayload, + GQLErrorPayload, + GQLMoveToolbarActionInput, + GQLMoveToolbarActionMutationData, + GQLMoveToolbarActionMutationVariables, + GQLMoveToolbarActionPayload, +} from './FormDescriptionEditorEventFragment.types'; +import { ToolbarActionsProps } from './ToolbarActions.types'; +import { ToolbarActionWidget } from './ToolbarActionWidget'; +import { isKind } from './WidgetOperations'; + +const useToolbarActionsStyles = makeStyles((theme: Theme) => ({ + toolbar: { + display: 'flex', + flexDirection: 'row', + justifyContent: 'flex-end', + }, + toolbarAction: { + whiteSpace: 'nowrap', + }, + toolbarActionDropArea: { + width: '20px', + }, + newToolbarAction: { + paddingLeft: theme.spacing(1), + }, + dragOver: { + border: 'dashed 1px red', + }, +})); + +const isErrorPayload = ( + payload: GQLAddToolbarActionPayload | GQLMoveToolbarActionPayload +): payload is GQLErrorPayload => payload.__typename === 'ErrorPayload'; + +export const ToolbarActions = ({ + editingContextId, + representationId, + formDescriptionEditor, + selection, + setSelection, +}: ToolbarActionsProps) => { + const classes = useToolbarActionsStyles(); + + const [message, setMessage] = useState(null); + + const [ + addToolbarAction, + { loading: addToolbarActionLoading, data: addToolbarActionData, error: addToolbarActionError }, + ] = useMutation(addToolbarActionMutation); + + useEffect(() => { + if (!addToolbarActionLoading) { + if (addToolbarActionError) { + setMessage(addToolbarActionError.message); + } + if (addToolbarActionData) { + const { addToolbarAction } = addToolbarActionData; + if (isErrorPayload(addToolbarAction)) { + setMessage(addToolbarAction.message); + } + } + } + }, [addToolbarActionLoading, addToolbarActionData, addToolbarActionError]); + + const [ + moveToolbarAction, + { loading: moveToolbarActionLoading, data: moveToolbarActionData, error: moveToolbarActionError }, + ] = useMutation(moveToolbarActionMutation); + + useEffect(() => { + if (!moveToolbarActionLoading) { + if (moveToolbarActionError) { + setMessage(moveToolbarActionError.message); + } + if (moveToolbarActionData) { + const { moveToolbarAction } = moveToolbarActionData; + if (isErrorPayload(moveToolbarAction)) { + setMessage(moveToolbarAction.message); + } + } + } + }, [moveToolbarActionLoading, moveToolbarActionData, moveToolbarActionError]); + + const handleAddToolbarAction: React.MouseEventHandler = () => { + const addToolbarActionInput: GQLAddToolbarActionInput = { + id: uuid(), + editingContextId, + representationId, + containerId: null, + }; + const addToolbarActionVariables: GQLAddToolbarActionMutationVariables = { input: addToolbarActionInput }; + addToolbarAction({ variables: addToolbarActionVariables }); + }; + + const handleDragEnter: React.DragEventHandler = (event) => { + event.preventDefault(); + event.currentTarget.classList.add(classes.dragOver); + }; + const handleDragOver: React.DragEventHandler = (event) => { + event.preventDefault(); + event.currentTarget.classList.add(classes.dragOver); + }; + const handleDragLeave: React.DragEventHandler = (event) => { + event.preventDefault(); + event.currentTarget.classList.remove(classes.dragOver); + }; + const handleDrop: React.DragEventHandler = (event) => { + event.preventDefault(); + event.currentTarget.classList.remove(classes.dragOver); + + const id: string = event.dataTransfer.getData('text/plain'); + let index = formDescriptionEditor.toolbarActions.length - 1; // Move at the end of the toolbar + + // We only accept drop of ToolbarAction, no other existing/new Widgets allowed + if (!isKind(id) && formDescriptionEditor.widgets.find((w) => w.id === id) === undefined) { + const moveToolbarActionInput: GQLMoveToolbarActionInput = { + id: uuid(), + editingContextId, + representationId, + containerId: null, + toolbarActionId: id, + index, + }; + const moveToolbarActionVariables: GQLMoveToolbarActionMutationVariables = { input: moveToolbarActionInput }; + moveToolbarAction({ variables: moveToolbarActionVariables }); + } + }; + + return ( +
+ {formDescriptionEditor.toolbarActions.map((toolbarAction) => ( +
+ +
+ ))} +
+
+ + + + + +
+ setMessage(null)} + message={message} + action={ + setMessage(null)}> + + + } + data-testid="error" + /> +
+ ); +}; diff --git a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ToolbarActions.types.ts b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ToolbarActions.types.ts new file mode 100644 index 0000000000..2ec2c216c3 --- /dev/null +++ b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/ToolbarActions.types.ts @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2022 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 { Selection } from '@eclipse-sirius/sirius-components-core'; +import { GQLFormDescriptionEditor } from './FormDescriptionEditorEventFragment.types'; + +export interface ToolbarActionsProps { + editingContextId: string; + representationId: string; + formDescriptionEditor: GQLFormDescriptionEditor; + selection: Selection; + setSelection: (newSelection: Selection) => void; +} diff --git a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/WidgetEntry.tsx b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/WidgetEntry.tsx index e704aee21a..86b2f9ccac 100644 --- a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/WidgetEntry.tsx +++ b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/WidgetEntry.tsx @@ -80,6 +80,7 @@ export const WidgetEntry = ({ editingContextId, representationId, containerId, + toolbarActions, siblings, widget, selection, @@ -230,7 +231,8 @@ export const WidgetEntry = ({ }; const addWidgetVariables: GQLAddWidgetMutationVariables = { input: addWidgetInput }; addWidget({ variables: addWidgetVariables }); - } else { + } else if (toolbarActions.find((w) => w.id === id) === undefined) { + // We only accept drop of Widgets, no ToolbarAction allowed const movedWidgetIndex = siblings.findIndex((w) => w.id === id); if (movedWidgetIndex > -1 && movedWidgetIndex < index) { index--; @@ -375,6 +377,7 @@ export const WidgetEntry = ({ data-testid={widget.id} editingContextId={editingContextId} representationId={representationId} + toolbarActions={toolbarActions} widget={widget as GQLFormDescriptionEditorFlexboxContainer} selection={selection} setSelection={setSelection} diff --git a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/WidgetEntry.types.ts b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/WidgetEntry.types.ts index 4a585b3e23..5ccaf2be6f 100644 --- a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/WidgetEntry.types.ts +++ b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/WidgetEntry.types.ts @@ -16,6 +16,7 @@ import React from 'react'; import { GQLAbstractFormDescriptionEditorWidget, GQLFormDescriptionEditorFlexboxContainer, + GQLFormDescriptionEditorToolbarAction, GQLFormDescriptionEditorWidget, } from './FormDescriptionEditorEventFragment.types'; @@ -23,6 +24,7 @@ export interface WidgetEntryProps { editingContextId: string; representationId: string; containerId: string | null; + toolbarActions: GQLFormDescriptionEditorToolbarAction[]; siblings: GQLAbstractFormDescriptionEditorWidget[]; widget: GQLAbstractFormDescriptionEditorWidget; selection: Selection; @@ -41,6 +43,7 @@ export interface WidgetProps { export interface FlexboxContainerWidgetProps { editingContextId: string; representationId: string; + toolbarActions: GQLFormDescriptionEditorToolbarAction[]; widget: GQLFormDescriptionEditorFlexboxContainer; selection: Selection; setSelection: (newSelection: Selection) => void; diff --git a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/__tests__/WidgetEntry.test.tsx b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/__tests__/WidgetEntry.test.tsx index 6648c73ebc..4d0189de13 100644 --- a/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/__tests__/WidgetEntry.test.tsx +++ b/packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors/src/__tests__/WidgetEntry.test.tsx @@ -121,6 +121,7 @@ test('should drop the Textfield in the drop area', async () => { editingContextId="editingContextId" representationId="formDescriptionEditorId" containerId={null} + toolbarActions={[]} siblings={[]} flexDirection={'row'} flexGrow={0} @@ -172,6 +173,7 @@ test('should delete the Textfield from the drop area', async () => { editingContextId="editingContextId" representationId="formDescriptionEditorId" containerId={null} + toolbarActions={[]} siblings={[]} flexDirection={'row'} flexGrow={0} @@ -222,6 +224,7 @@ test('should delete the PieChart from the drop area', async () => { editingContextId="editingContextId" representationId="formDescriptionEditorId" containerId={null} + toolbarActions={[]} siblings={[]} flexDirection={'row'} flexGrow={0} @@ -271,6 +274,7 @@ test('should move the existing Textfield from/into the drop area', async () => { editingContextId="editingContextId" representationId="formDescriptionEditorId" containerId={null} + toolbarActions={[]} siblings={[]} flexDirection={'row'} flexGrow={0} diff --git a/packages/forms/backend/sirius-components-collaborative-forms/src/main/java/org/eclipse/sirius/components/collaborative/forms/FormQueryService.java b/packages/forms/backend/sirius-components-collaborative-forms/src/main/java/org/eclipse/sirius/components/collaborative/forms/FormQueryService.java index 9531f7afdb..1b64701160 100644 --- a/packages/forms/backend/sirius-components-collaborative-forms/src/main/java/org/eclipse/sirius/components/collaborative/forms/FormQueryService.java +++ b/packages/forms/backend/sirius-components-collaborative-forms/src/main/java/org/eclipse/sirius/components/collaborative/forms/FormQueryService.java @@ -19,9 +19,9 @@ import org.eclipse.sirius.components.collaborative.forms.api.IFormQueryService; import org.eclipse.sirius.components.forms.AbstractWidget; +import org.eclipse.sirius.components.forms.FlexboxContainer; import org.eclipse.sirius.components.forms.Form; import org.eclipse.sirius.components.forms.Group; -import org.eclipse.sirius.components.forms.FlexboxContainer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; @@ -56,6 +56,7 @@ public Optional findWidget(Form form, String widgetId) { private List getAllWidgets(Group group) { List widgets = new ArrayList<>(); + group.getToolbarActions().forEach(widgets::add); group.getWidgets().forEach(widget -> { if (widget instanceof FlexboxContainer) { widgets.addAll(this.getAllWidgets((FlexboxContainer) widget)); diff --git a/packages/forms/backend/sirius-components-collaborative-forms/src/main/resources/schema/form.graphqls b/packages/forms/backend/sirius-components-collaborative-forms/src/main/resources/schema/form.graphqls index 2a67abe0e8..dfe1952401 100644 --- a/packages/forms/backend/sirius-components-collaborative-forms/src/main/resources/schema/form.graphqls +++ b/packages/forms/backend/sirius-components-collaborative-forms/src/main/resources/schema/form.graphqls @@ -61,6 +61,7 @@ type Group { id: ID! label: String! displayMode: GroupDisplayMode! + toolbarActions: [Button!]! widgets: [Widget!]! } diff --git a/packages/forms/backend/sirius-components-forms-graphql/src/main/java/org/eclipse/sirius/components/forms/graphql/datafetchers/form/ButtonImageURLDataFetcher.java b/packages/forms/backend/sirius-components-forms-graphql/src/main/java/org/eclipse/sirius/components/forms/graphql/datafetchers/form/ButtonImageURLDataFetcher.java index 1ff53ba414..0e27ec1d62 100644 --- a/packages/forms/backend/sirius-components-forms-graphql/src/main/java/org/eclipse/sirius/components/forms/graphql/datafetchers/form/ButtonImageURLDataFetcher.java +++ b/packages/forms/backend/sirius-components-forms-graphql/src/main/java/org/eclipse/sirius/components/forms/graphql/datafetchers/form/ButtonImageURLDataFetcher.java @@ -31,10 +31,16 @@ public class ButtonImageURLDataFetcher implements IDataFetcherWithFieldCoordinates { @Override public String get(DataFetchingEnvironment environment) throws Exception { + String imageURL = null; Button button = environment.getSource(); - if (button.getImageURL() != null && !button.getImageURL().isBlank()) { - return URLConstants.IMAGE_BASE_PATH + button.getImageURL(); + String buttonImageURL = button.getImageURL(); + if (buttonImageURL != null && !buttonImageURL.isBlank()) { + if (buttonImageURL.startsWith("http://") || buttonImageURL.startsWith("https://")) { //$NON-NLS-1$ //$NON-NLS-2$ + imageURL = buttonImageURL; + } else { + imageURL = URLConstants.IMAGE_BASE_PATH + buttonImageURL; + } } - return null; + return imageURL; } } diff --git a/packages/forms/backend/sirius-components-forms/src/main/java/org/eclipse/sirius/components/forms/Group.java b/packages/forms/backend/sirius-components-forms/src/main/java/org/eclipse/sirius/components/forms/Group.java index 05dee1cc14..d5f5966084 100644 --- a/packages/forms/backend/sirius-components-forms/src/main/java/org/eclipse/sirius/components/forms/Group.java +++ b/packages/forms/backend/sirius-components-forms/src/main/java/org/eclipse/sirius/components/forms/Group.java @@ -31,6 +31,8 @@ public final class Group { private GroupDisplayMode displayMode; + private List